X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_player.pas;h=f2dc59a787a98b389265177187459089ee8c2621;hb=c2809bc43b3c99586d523e90b00272280a9cd69b;hp=da4c43a84e12561afef525e41c84ce7eb8e04d4a;hpb=fbedc3eec9e72225010d043d2be17b44cf13941e;p=d2df-sdl.git diff --git a/src/game/g_player.pas b/src/game/g_player.pas index da4c43a..f2dc59a 100644 --- a/src/game/g_player.pas +++ b/src/game/g_player.pas @@ -2,8 +2,7 @@ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * the Free Software Foundation, version 3 of the License ONLY. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -97,6 +96,8 @@ const SUICIDE_DAMAGE = 112; WEAPON_DELAY = 5; + PLAYER_BURN_TIME = 110; + PLAYER1_DEF_COLOR: TRGB = (R:64; G:175; B:48); PLAYER2_DEF_COLOR: TRGB = (R:96; G:96; B:96); @@ -266,6 +267,8 @@ type FReady: Boolean; FDummy: Boolean; FFireTime: Integer; + FHandicap: Integer; + FWaitForFirstSpawn: Boolean; // set to `true` in server, used to spawn a player on first full state request // debug: viewport offset viewPortX, viewPortY, viewPortW, viewPortH: Integer; @@ -280,6 +283,7 @@ type procedure ReleaseKeys(); procedure SetModel(ModelName: String); procedure SetColor(Color: TRGB); + function GetColor(): TRGB; procedure SetWeapon(W: Byte); function IsKeyPressed(K: Byte): Boolean; function GetKeys(): Byte; @@ -317,7 +321,7 @@ type procedure DrawPickup(); procedure DrawRulez(); procedure DrawAim(); - procedure DrawIndicator(); + procedure DrawIndicator(Color: TRGB); procedure DrawBubble(); procedure DrawGUI(); procedure Update(); virtual; @@ -335,7 +339,7 @@ type procedure FlamerOff; procedure JetpackOn; procedure JetpackOff; - procedure CatchFire(Attacker: Word); + procedure CatchFire(Attacker: Word; Timeout: Integer = PLAYER_BURN_TIME); //WARNING! this does nothing for now, but still call it! procedure positionChanged (); //WARNING! call this after entity position was changed, or coldet will not work right! @@ -551,8 +555,9 @@ var gTeamStat: TTeamStat; gFly: Boolean = False; gAimLine: Boolean = False; - gChatBubble: Byte = 0; - gPlayerIndicator: Boolean = True; + gChatBubble: Integer = 0; + gPlayerIndicator: Integer = 1; + gPlayerIndicatorStyle: Integer = 0; gNumBots: Word = 0; gLMSPID1: Word = 0; gLMSPID2: Word = 0; @@ -595,8 +600,8 @@ procedure g_Player_RemoveAllCorpses(); procedure g_Player_Corpses_SaveState (st: TStream); procedure g_Player_Corpses_LoadState (st: TStream); procedure g_Player_ResetReady(); -procedure g_Bot_Add(Team, Difficult: Byte); -procedure g_Bot_AddList(Team: Byte; lname: ShortString; num: Integer = -1); +procedure g_Bot_Add(Team, Difficult: Byte; Handicap: Integer = 100); +procedure g_Bot_AddList(Team: Byte; lname: ShortString; num: Integer = -1; Handicap: Integer = 100); procedure g_Bot_MixNames(); procedure g_Bot_RemoveAll(); @@ -608,7 +613,7 @@ uses g_holmes, {$ENDIF} e_log, g_map, g_items, g_console, g_gfx, Math, - g_options, g_triggers, g_menu, g_game, g_grid, + g_options, g_triggers, g_menu, g_game, g_grid, e_res, wadreader, g_main, g_monsters, CONFIG, g_language, g_net, g_netmsg, g_window, utils, xstreams; @@ -885,6 +890,8 @@ begin if b = 1 then gPlayers[a].FDirection := TDirection.D_LEFT else gPlayers[a].FDirection := TDirection.D_RIGHT; // b = 2 // Çäîðîâüå gPlayers[a].FHealth := utils.readLongInt(st); + // Ôîðà + gPlayers[a].FHandicap := utils.readLongInt(st); // Æèçíè gPlayers[a].FLives := utils.readByte(st); // Áðîíÿ @@ -1006,7 +1013,7 @@ begin end; end; -procedure g_Bot_Add(Team, Difficult: Byte); +procedure g_Bot_Add(Team, Difficult: Byte; Handicap: Integer = 100); var m: SSArray; _name, _model: String; @@ -1095,6 +1102,8 @@ begin //FDifficult.SafeWeaponPrior[a] := WEAPON_PRIOR3[a]; end; + FHandicap := Handicap; + g_Console_Add(Format(_lc[I_PLAYER_JOIN], [Name]), True); if g_Game_IsNet then MH_SEND_PlayerCreate(UID); @@ -1103,7 +1112,7 @@ begin end; end; -procedure g_Bot_AddList(Team: Byte; lName: ShortString; num: Integer = -1); +procedure g_Bot_AddList(Team: Byte; lName: ShortString; num: Integer = -1; Handicap: Integer = 100); var m: SSArray; _name, _model: String; @@ -1166,6 +1175,8 @@ begin FDifficult.Cover := BotList[num].cover; FDifficult.CloseJump := BotList[num].close_jump; + FHandicap := Handicap; + for a := WP_FIRST to WP_LAST do begin FDifficult.WeaponPrior[a] := BotList[num].w_prior1[a]; @@ -1243,14 +1254,16 @@ var a, b: Integer; config: TConfig; sa: SSArray; + path: AnsiString; begin BotNames := nil; - if not FileExists(DataDir + BOTNAMES_FILENAME) then + path := BOTNAMES_FILENAME; + if e_FindResource(DataDirs, path) = false then Exit; // ×èòàåì âîçìîæíûå èìåíà áîòîâ èç ôàéëà: - AssignFile(F, DataDir + BOTNAMES_FILENAME); + AssignFile(F, path); Reset(F); while not EOF(F) do @@ -1271,7 +1284,7 @@ begin g_Bot_MixNames(); // ×èòàåì ôàéë ñ ïàðàìåòðàìè áîòîâ: - config := TConfig.CreateFile(DataDir + BOTLIST_FILENAME); + config := TConfig.CreateFile(path); BotList := nil; a := 0; @@ -2026,6 +2039,11 @@ begin if FModel <> nil then FModel.Color := Color; end; +function TPlayer.GetColor(): TRGB; +begin + result := FModel.Color; +end; + procedure TPlayer.SwitchTeam; begin if g_Game_IsClient then @@ -2152,6 +2170,7 @@ begin FFireTime := 0; FFirePainTime := 0; FFireAttacker := 0; + FHandicap := 100; FActualModelName := 'doomer'; @@ -2162,6 +2181,8 @@ begin FJustTeleported := False; FNetTime := 0; + FWaitForFirstSpawn := false; + resetWeaponQueue(); end; @@ -2312,23 +2333,72 @@ begin inherited; end; -procedure TPlayer.DrawIndicator(); +procedure TPlayer.DrawIndicator(Color: TRGB); var indX, indY: Integer; indW, indH: Word; + indA: Single; + a: TDFPoint; + nW, nH: Byte; ID: DWORD; + c: TRGB; begin if FAlive then - begin - indX := FObj.X+FObj.Rect.X; - indY := FObj.Y; - if g_Texture_Get('TEXTURE_PLAYER_INDICATOR', ID) then + case gPlayerIndicatorStyle of + 0: begin - e_GetTextureSize(ID, @indW, @indH); - e_Draw(ID, indX + indW div 2, indY - indH, 0, True, False); + if g_Texture_Get('TEXTURE_PLAYER_INDICATOR', ID) then + begin + e_GetTextureSize(ID, @indW, @indH); + a.X := indW div 2; + a.Y := indH div 2; + + if (FObj.X + FObj.Rect.X) < 0 then + begin + indA := 90; + indX := FObj.X + FObj.Rect.X + FObj.Rect.Width; + indY := FObj.Y + FObj.Rect.Y + (FObj.Rect.Height - indW) div 2; + end + + else if (FObj.X + FObj.Rect.X + FObj.Rect.Width) > Max(gMapInfo.Width, gPlayerScreenSize.X) then + begin + indA := 270; + indX := FObj.X + FObj.Rect.X - indH; + indY := FObj.Y + FObj.Rect.Y + (FObj.Rect.Height - indW) div 2; + end + + else if (fObj.Y - indH) < 0 then + begin + indA := 180; + indX := FObj.X + FObj.Rect.X + (FObj.Rect.Width - indW) div 2; + indY := FObj.Y + FObj.Rect.Y + FObj.Rect.Height; + end + + else + begin + indA := 0; + indX := FObj.X + FObj.Rect.X + (FObj.Rect.Width - indW) div 2; + indY := FObj.Y - indH; + end; + + indX := EnsureRange(indX, 0, Max(gMapInfo.Width, gPlayerScreenSize.X) - indW); + indY := EnsureRange(indY, 0, Max(gMapInfo.Height, gPlayerScreenSize.Y) - indH); + + c := e_Colors; + e_Colors := Color; + e_DrawAdv(ID, indX, indY, 0, True, False, indA, @a); + e_Colors := c; + end; + end; + + 1: + begin + e_TextureFontGetSize(gStdFont, nW, nH); + indX := FObj.X + FObj.Rect.X + (FObj.Rect.Width - Length(FName) * nW) div 2; + indY := FObj.Y - nH; + e_TextureFontPrintEx(indX, indY, FName, gStdFont, Color.R, Color.G, Color.B, 1.0, True); end; end; - //e_TextureFontPrint(indX, indY, FName, gStdFont); // Shows player name overhead end; procedure TPlayer.DrawBubble(); @@ -3181,11 +3251,17 @@ begin FJetSoundOff.PlayAt(FObj.X, FObj.Y); end; -procedure TPlayer.CatchFire(Attacker: Word); +procedure TPlayer.CatchFire(Attacker: Word; Timeout: Integer = PLAYER_BURN_TIME); begin + if Timeout <= 0 then + exit; + if (FMegaRulez[MR_SUIT] > gTime) or (FMegaRulez[MR_INVUL] > gTime) then + exit; // Íå çàãîðàåìñÿ êîãäà åñòü çàùèòà + if g_Obj_CollidePanel(@FObj, 0, 0, PANEL_WATER or PANEL_ACID1 or PANEL_ACID2) then + exit; // Íå ïîäãîðàåì â âîäå íà âñÿêèé ñëó÷àé if FFireTime <= 0 then g_Sound_PlayExAt('SOUND_IGNITE', FObj.X, FObj.Y); - FFireTime := 100; + FFireTime := Timeout; FFireAttacker := Attacker; if g_Game_IsNet and g_Game_IsServer then MH_SEND_PlayerStats(FUID); @@ -3841,9 +3917,9 @@ begin case ItemType of ITEM_MEDKIT_SMALL: - if FHealth < PLAYER_HP_SOFT then + if (FHealth < PLAYER_HP_SOFT) or (FFireTime > 0) then begin - IncMax(FHealth, 10, PLAYER_HP_SOFT); + if FHealth < PLAYER_HP_SOFT then IncMax(FHealth, 10, PLAYER_HP_SOFT); Result := True; remove := True; FFireTime := 0; @@ -3851,9 +3927,9 @@ begin end; ITEM_MEDKIT_LARGE: - if FHealth < PLAYER_HP_SOFT then + if (FHealth < PLAYER_HP_SOFT) or (FFireTime > 0) then begin - IncMax(FHealth, 25, PLAYER_HP_SOFT); + if FHealth < PLAYER_HP_SOFT then IncMax(FHealth, 25, PLAYER_HP_SOFT); Result := True; remove := True; FFireTime := 0; @@ -3879,9 +3955,9 @@ begin end; ITEM_SPHERE_BLUE: - if FHealth < PLAYER_HP_LIMIT then + if (FHealth < PLAYER_HP_LIMIT) or (FFireTime > 0) then begin - IncMax(FHealth, 100, PLAYER_HP_LIMIT); + if FHealth < PLAYER_HP_LIMIT then IncMax(FHealth, 100, PLAYER_HP_LIMIT); Result := True; remove := True; FFireTime := 0; @@ -3889,7 +3965,7 @@ begin end; ITEM_SPHERE_WHITE: - if (FHealth < PLAYER_HP_LIMIT) or (FArmor < PLAYER_AP_LIMIT) then + if (FHealth < PLAYER_HP_LIMIT) or (FArmor < PLAYER_AP_LIMIT) or (FFireTime > 0) then begin if FHealth < PLAYER_HP_LIMIT then FHealth := PLAYER_HP_LIMIT; @@ -4094,7 +4170,7 @@ begin (FAmmo[A_SHELLS] < FMaxAmmo[A_SHELLS]) or (FAmmo[A_ROCKETS] < FMaxAmmo[A_ROCKETS]) or (FAmmo[A_CELLS] < FMaxAmmo[A_CELLS]) or - (FMaxAmmo[A_FUEL] < AmmoLimits[1, A_FUEL]) then + (FAmmo[A_FUEL] < FMaxAmmo[A_FUEL]) then begin FMaxAmmo[A_BULLETS] := AmmoLimits[1, A_BULLETS]; FMaxAmmo[A_SHELLS] := AmmoLimits[1, A_SHELLS]; @@ -4110,6 +4186,8 @@ begin IncMax(FAmmo[A_ROCKETS], 1, FMaxAmmo[A_ROCKETS]); if FAmmo[A_CELLS] < FMaxAmmo[A_CELLS] then IncMax(FAmmo[A_CELLS], 40, FMaxAmmo[A_CELLS]); + if FAmmo[A_FUEL] < FMaxAmmo[A_FUEL] then + IncMax(FAmmo[A_FUEL], 50, FMaxAmmo[A_FUEL]); FRulez := FRulez + [R_ITEM_BACKPACK]; Result := True; @@ -4187,9 +4265,9 @@ begin remove := True; FFireTime := 0; end; - if FHealth < PLAYER_HP_SOFT then + if (FHealth < PLAYER_HP_SOFT) or (FFireTime > 0) then begin - FHealth := PLAYER_HP_SOFT; + if FHealth < PLAYER_HP_SOFT then FHealth := PLAYER_HP_SOFT; FBerserk := gTime+30000; Result := True; remove := True; @@ -4207,9 +4285,9 @@ begin end; ITEM_BOTTLE: - if FHealth < PLAYER_HP_LIMIT then + if (FHealth < PLAYER_HP_LIMIT) or (FFireTime > 0) then begin - IncMax(FHealth, 4, PLAYER_HP_LIMIT); + if FHealth < PLAYER_HP_LIMIT then IncMax(FHealth, 4, PLAYER_HP_LIMIT); Result := True; remove := True; FFireTime := 0; @@ -4526,7 +4604,7 @@ begin // Âîñêðåøåíèå áåç îðóæèÿ: if not FAlive then begin - FHealth := PLAYER_HP_SOFT; + FHealth := Round(PLAYER_HP_SOFT * (FHandicap / 100)); FArmor := 0; FAlive := True; FAir := AIR_DEF; @@ -5266,11 +5344,13 @@ begin if FFirePainTime <= 0 then begin if g_Game_IsServer then - Damage(5, FFireAttacker, 0, 0, HIT_FLAME); - FFirePainTime := 18; + Damage(2, FFireAttacker, 0, 0, HIT_FLAME); + FFirePainTime := 12 - FFireTime div 12; end; FFirePainTime := FFirePainTime - 1; FFireTime := FFireTime - 1; + if ((FFireTime mod 33) = 0) and (FMegaRulez[MR_INVUL] < gTime) then + FModel.PlaySound(MODELSOUND_PAIN, 1, FObj.X, FObj.Y); if (FFireTime = 0) and g_Game_IsNet and g_Game_IsServer then MH_SEND_PlayerStats(FUID); end; @@ -5302,7 +5382,7 @@ begin else if FHealth > -50 then Kill(K_HARDKILL, FLastSpawnerUID, FLastHit) else Kill(K_EXTRAHARDKILL, FLastSpawnerUID, FLastHit); - if FAlive then + if FAlive and ((FLastHit <> HIT_FLAME) or (FFireTime <= 0)) then begin if FDamageBuffer <= 20 then FModel.PlaySound(MODELSOUND_PAIN, 1, FObj.X, FObj.Y) else if FDamageBuffer <= 55 then FModel.PlaySound(MODELSOUND_PAIN, 2, FObj.X, FObj.Y) @@ -5924,6 +6004,8 @@ begin utils.writeInt(st, Byte(b)); // Çäîðîâüå utils.writeInt(st, LongInt(FHealth)); + // Êîýôôèöèåíò èíâàëèäíîñòè + utils.writeInt(st, LongInt(FHandicap)); // Æèçíè utils.writeInt(st, Byte(FLives)); // Áðîíÿ @@ -6026,6 +6108,8 @@ begin if b = 1 then FDirection := TDirection.D_LEFT else FDirection := TDirection.D_RIGHT; // b = 2 // Çäîðîâüå FHealth := utils.readLongInt(st); + // Êîýôôèöèåíò èíâàëèäíîñòè + FHandicap := utils.readLongInt(st); // Æèçíè FLives := utils.readByte(st); // Áðîíÿ @@ -7864,4 +7948,6 @@ end; begin conRegVar('cheat_berserk_autoswitch', @gBerserkAutoswitch, 'autoswitch to fist when berserk pack taken', '', true, true); + conRegVar('player_indicator', @gPlayerIndicator, 'Draw indicator only for current player, also for teammates, or not at all', 'Draw indicator only for current player, also for teammates, or not at all'); + conRegVar('player_indicator_style', @gPlayerIndicatorStyle, 'Visual appearance of indicator', 'Visual appearance of indicator'); end.