X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_monsters.pas;h=5fa50114660f43d7a5df764ce662a16ab4b11b0f;hb=d52e9d7b6bcc5c1846c82c3908a4688339e736f3;hp=cd660a29d5a32b034fa0188b869720ce1a34d724;hpb=b8b3691f5a4d6537539f557588cfd6fab79ed4b6;p=d2df-sdl.git diff --git a/src/game/g_monsters.pas b/src/game/g_monsters.pas index cd660a2..5fa5011 100644 --- a/src/game/g_monsters.pas +++ b/src/game/g_monsters.pas @@ -23,7 +23,7 @@ uses SysUtils, Classes, mempool, MAPDEF, - g_base, g_basic, g_phys, g_textures, g_grid, + g_base, g_basic, g_phys, g_animations, g_grid, g_saveload, g_panel, xprofiler; const @@ -52,7 +52,7 @@ const } type - ADirectedAnim = Array of Array [TDirection.D_LEFT..TDirection.D_RIGHT] of TAnimationState; + ADirectedAnim = Array of Array [TDirection.D_LEFT..TDirection.D_RIGHT] of TAnimState; PMonster = ^TMonster; TMonster = class{$IFDEF USE_MEMPOOL}(TPoolObject){$ENDIF} @@ -93,7 +93,7 @@ type {$ENDIF} FFirePainTime: Integer; FFireAttacker: Word; - vilefire: TAnimationState; + FVileFireTime: LongWord; mProxyId: Integer; // node in dyntree or -1 mArrIdx: Integer; // in gMonsters @@ -198,7 +198,7 @@ type property StartID: Integer read FStartID; - property VileFireAnim: TAnimationState read vilefire; + property VileFireTime: LongWord read FVileFireTime; property DirAnim: ADirectedAnim read FAnim; published @@ -328,6 +328,7 @@ var ANIM_ATTACK = 4; ANIM_ATTACK2 = 5; ANIM_PAIN = 6; + ANIM_LAST = ANIM_PAIN; // Таблица характеристик монстров: MONSTERTABLE: Array [MONSTER_DEMON..MONSTER_MAN] of @@ -537,8 +538,11 @@ uses {$IFDEF ENABLE_SHELLS} g_shells, {$ENDIF} + {$IFDEF ENABLE_CORPSES} + g_corpses, + {$ENDIF} e_log, g_sound, g_player, g_game, - g_weapons, g_triggers, g_items, g_options, + g_weapons, g_triggers, g_items, g_options, g_window, g_console, g_map, Math, wadreader, g_language, g_netmsg, idpool, utils, xstreams; @@ -892,10 +896,6 @@ end; procedure g_Monsters_LoadData(); begin e_WriteLog('Loading monsters data...', TMsgType.Notify); - - g_Game_SetLoadingText(_lc[I_LOAD_MONSTER_TEXTURES], 133, False); - g_Game_StepLoading(133); - g_Game_SetLoadingText(_lc[I_LOAD_MONSTER_SOUNDS], 0, False); g_Sound_CreateWADEx('SOUND_MONSTER_BARREL_DIE', GameWAD+':MSOUNDS\BARREL_DIE'); @@ -1678,11 +1678,11 @@ begin SetLength(FAnim, Length(ANIMTABLE)); for a := ANIM_SLEEP to ANIM_PAIN do begin - FAnim[a, TDirection.D_RIGHT] := TAnimationState.Create(ANIMTABLE[a].loop, MONSTER_ANIMTABLE[MonsterType].AnimSpeed[a], MONSTER_ANIMTABLE[MonsterType].AnimCount[a]); - FAnim[a, TDirection.D_LEFT] := TAnimationState.Create(ANIMTABLE[a].loop, MONSTER_ANIMTABLE[MonsterType].AnimSpeed[a], MONSTER_ANIMTABLE[MonsterType].AnimCount[a]); + FAnim[a, TDirection.D_RIGHT] := TAnimState.Create(ANIMTABLE[a].loop, MONSTER_ANIMTABLE[MonsterType].AnimSpeed[a], MONSTER_ANIMTABLE[MonsterType].AnimCount[a]); + FAnim[a, TDirection.D_LEFT] := TAnimState.Create(ANIMTABLE[a].loop, MONSTER_ANIMTABLE[MonsterType].AnimSpeed[a], MONSTER_ANIMTABLE[MonsterType].AnimCount[a]); end; - if MonsterType = MONSTER_VILE then - vilefire := TAnimationState.Create(True, 2, 8); + + FVileFireTime := gTime; end; function TMonster.Damage(aDamage: Word; VelX, VelY: Integer; SpawnerUID: Word; t: Byte): Boolean; @@ -1875,11 +1875,11 @@ var begin for a := 0 to High(FAnim) do begin - FAnim[a, TDirection.D_LEFT].Free(); - FAnim[a, TDirection.D_RIGHT].Free(); + FAnim[a, TDirection.D_LEFT].Invalidate; + FAnim[a, TDirection.D_RIGHT].Invalidate; end; - vilefire.Free(); + FVileFireTime := 0; if (mProxyId <> -1) then begin @@ -1986,7 +1986,7 @@ begin // Если анимация новая - перезапускаем её: if FCurAnim <> Anim then - if FAnim[Anim, FDirection] <> nil then + if FAnim[Anim, FDirection].IsValid() then begin FAnim[Anim, FDirection].Reset(); FCurAnim := Anim; @@ -2070,14 +2070,20 @@ begin end; procedure TMonster.Update(); -var - a, b, sx, sy, wx, wy, oldvelx: Integer; - st: Word; - o, co: TObj; - fall, bubbles: Boolean; - mon: TMonster; - mit: PMonster; - it: TMonsterGrid.Iter; + {$IFDEF ENABLE_CORPSES} + var co: TObj; + {$ENDIF} + {$IF DEFINED(ENABLE_GIBS) OR DEFINED(ENABLE_CORPSES)} + var b: Integer; + {$ENDIF} + var + a, sx, sy, wx, wy, oldvelx: Integer; + st: Word; + o: TObj; + fall, bubbles: Boolean; + mon: TMonster; + mit: PMonster; + it: TMonsterGrid.Iter; label _end; begin @@ -2545,25 +2551,27 @@ begin end; end; {$ENDIF} - // Боссы могут пинать трупы: - if (FMonsterType in [MONSTER_CYBER, MONSTER_SPIDER, MONSTER_ROBO]) and - (FObj.Vel.X <> 0) and (gCorpses <> nil) then - begin - b := Abs(FObj.Vel.X); - if b > 1 then b := b * (Random(8 div b) + 1); - for a := 0 to High(gCorpses) do - if (gCorpses[a] <> nil) and (gCorpses[a].State > 0) then - begin - co := gCorpses[a].Obj; - if g_Obj_Collide(FObj.X+FObj.Rect.X, FObj.Y+FObj.Rect.Y+FObj.Rect.Height-4, - FObj.Rect.Width, 8, @co) and (Random(3) = 0) then - // Пинаем трупы - if FObj.Vel.X < 0 then - gCorpses[a].Damage(b*2, FUID, -b, Random(7)) // налево - else - gCorpses[a].Damage(b*2, FUID, b, Random(7)); // направо - end; - end; + {$IFDEF ENABLE_CORPSES} + // Боссы могут пинать трупы: + if (FMonsterType in [MONSTER_CYBER, MONSTER_SPIDER, MONSTER_ROBO]) and + (FObj.Vel.X <> 0) and (gCorpses <> nil) then + begin + b := Abs(FObj.Vel.X); + if b > 1 then b := b * (Random(8 div b) + 1); + for a := 0 to High(gCorpses) do + if (gCorpses[a] <> nil) and (gCorpses[a].State > 0) then + begin + co := gCorpses[a].Obj; + if g_Obj_Collide(FObj.X+FObj.Rect.X, FObj.Y+FObj.Rect.Y+FObj.Rect.Height-4, + FObj.Rect.Width, 8, @co) and (Random(3) = 0) then + // Пинаем трупы + if FObj.Vel.X < 0 then + gCorpses[a].Damage(b*2, FUID, -b, Random(7)) // налево + else + gCorpses[a].Damage(b*2, FUID, b, Random(7)); // направо + end; + end; + {$ENDIF} // Если цель высоко, то, возможно, прыгаем: if sy < -40 then if g_Obj_CollideLevel(@FObj, 0, 1) or g_Obj_StayOnStep(@FObj) then @@ -2765,13 +2773,9 @@ _end: SetState(MONSTATE_GO); end; -// Если есть анимация огня колдуна - пусть она идет: - if vilefire <> nil then - vilefire.Update(); - // Состояние - Умирает и текущая анимация проиграна: if (FState = MONSTATE_DIE) and - (FAnim[FCurAnim, FDirection] <> nil) and + (FAnim[FCurAnim, FDirection].IsValid()) and (FAnim[FCurAnim, FDirection].Played) then begin // Умер: @@ -2822,7 +2826,7 @@ _end: // Совершение атаки и стрельбы: if (FState = MONSTATE_ATTACK) or (FState = MONSTATE_SHOOT) then - if (FAnim[FCurAnim, FDirection] <> nil) then + if (FAnim[FCurAnim, FDirection].IsValid()) then // Анимация атаки есть - можно атаковать if (FAnim[FCurAnim, FDirection].Played) then begin // Анимация атаки закончилась => переходим на шаг @@ -3063,7 +3067,7 @@ _end: FObj.Vel.X := oldvelx; // Если есть анимация, то пусть она идет: - if FAnim[FCurAnim, FDirection] <> nil then + if FAnim[FCurAnim, FDirection].IsValid() then FAnim[FCurAnim, FDirection].Update(); end; @@ -3089,11 +3093,14 @@ begin end; procedure TMonster.ClientUpdate(); -var - a, b, sx, sy, oldvelx: Integer; - st: Word; - o, co: TObj; - fall, bubbles: Boolean; + {$IFDEF ENABLE_CORPSES} + var a, b: Integer; co: TObj; + {$ENDIF} + var + sx, sy, oldvelx: Integer; + st: Word; + o: TObj; + fall, bubbles: Boolean; label _end; begin @@ -3420,25 +3427,27 @@ begin end; end; {$ENDIF} - // Боссы могут пинать трупы: - if (FMonsterType in [MONSTER_CYBER, MONSTER_SPIDER, MONSTER_ROBO]) and - (FObj.Vel.X <> 0) and (gCorpses <> nil) then - begin - b := Abs(FObj.Vel.X); - if b > 1 then b := b * (Random(8 div b) + 1); - for a := 0 to High(gCorpses) do - if (gCorpses[a] <> nil) and (gCorpses[a].State > 0) then - begin - co := gCorpses[a].Obj; - if g_Obj_Collide(FObj.X+FObj.Rect.X, FObj.Y+FObj.Rect.Y+FObj.Rect.Height-4, - FObj.Rect.Width, 8, @co) and (Random(3) = 0) then - // Пинаем трупы - if FObj.Vel.X < 0 then - gCorpses[a].Damage(b*2, FUID, -b, Random(7)) // налево - else - gCorpses[a].Damage(b*2, FUID, b, Random(7)); // направо - end; - end; + {$IFDEF ENABLE_CORPSES} + // Боссы могут пинать трупы: + if (FMonsterType in [MONSTER_CYBER, MONSTER_SPIDER, MONSTER_ROBO]) and + (FObj.Vel.X <> 0) and (gCorpses <> nil) then + begin + b := Abs(FObj.Vel.X); + if b > 1 then b := b * (Random(8 div b) + 1); + for a := 0 to High(gCorpses) do + if (gCorpses[a] <> nil) and (gCorpses[a].State > 0) then + begin + co := gCorpses[a].Obj; + if g_Obj_Collide(FObj.X+FObj.Rect.X, FObj.Y+FObj.Rect.Y+FObj.Rect.Height-4, + FObj.Rect.Width, 8, @co) and (Random(3) = 0) then + // Пинаем трупы + if FObj.Vel.X < 0 then + gCorpses[a].Damage(b*2, FUID, -b, Random(7)) // налево + else + gCorpses[a].Damage(b*2, FUID, b, Random(7)); // направо + end; + end; + {$ENDIF} end; FSleep := FSleep + 1; @@ -3623,13 +3632,9 @@ _end: SetState(MONSTATE_GO); end; -// Если есть анимация огня колдуна - пусть она идет: - if vilefire <> nil then - vilefire.Update(); - // Состояние - Умирает и текущая анимация проиграна: if (FState = MONSTATE_DIE) and - (FAnim[FCurAnim, FDirection] <> nil) and + (FAnim[FCurAnim, FDirection].IsValid()) and (FAnim[FCurAnim, FDirection].Played) then begin // Умер: @@ -3646,7 +3651,7 @@ _end: // Совершение атаки и стрельбы: if (FState = MONSTATE_ATTACK) or (FState = MONSTATE_SHOOT) then - if (FAnim[FCurAnim, FDirection] <> nil) then + if (FAnim[FCurAnim, FDirection].IsValid()) then // Анимация атаки есть - можно атаковать if (FAnim[FCurAnim, FDirection].Played) then begin // Анимация атаки закончилась => переходим на шаг @@ -3772,7 +3777,7 @@ _end: FObj.Vel.X := oldvelx; // Если есть анимация, то пусть она идет: - if FAnim[FCurAnim, FDirection] <> nil then + if FAnim[FCurAnim, FDirection].IsValid() then FAnim[FCurAnim, FDirection].Update(); end; @@ -4098,7 +4103,7 @@ begin ty := o^.Y+o^.Rect.Y; SetState(MONSTATE_SHOOT); - vilefire.Reset(); + FVileFireTime := gTime; g_Sound_PlayExAt('SOUND_MONSTER_VILE_ATTACK', FObj.X, FObj.Y); g_Sound_PlayExAt('SOUND_FIRE', o^.X, o^.Y); @@ -4161,6 +4166,7 @@ var i: Integer; b: Byte; anim: Boolean; + stub: TAnimState; begin assert(st <> nil); @@ -4210,20 +4216,25 @@ begin // Объект монстра Obj_SaveState(st, @FObj); // Есть ли анимация огня колдуна - anim := (vilefire <> nil); + anim := FMonsterType = MONSTER_VILE; utils.writeBool(st, anim); // Если есть - сохраняем: - if anim then vilefire.SaveState(st, 0, False); + if anim then + begin + stub := TAnimState.Create(true, 2, 8); + stub.SaveState(st, 0, False); + stub.Invalidate; + end; // Анимации for i := ANIM_SLEEP to ANIM_PAIN do begin // Есть ли левая анимация - anim := (FAnim[i, TDirection.D_LEFT] <> nil); + anim := (FAnim[i, TDirection.D_LEFT].IsValid()); utils.writeBool(st, anim); // Если есть - сохраняем if anim then FAnim[i, TDirection.D_LEFT].SaveState(st, 0, False); // Есть ли правая анимация - anim := (FAnim[i, TDirection.D_RIGHT] <> nil); + anim := (FAnim[i, TDirection.D_RIGHT].IsValid()); utils.writeBool(st, anim); // Если есть - сохраняем if anim then FAnim[i, TDirection.D_RIGHT].SaveState(st, 0, False); @@ -4236,6 +4247,7 @@ var i: Integer; b, alpha: Byte; anim, blending: Boolean; + stub: TAnimState; begin assert(st <> nil); @@ -4294,9 +4306,11 @@ begin // Если есть - загружаем: if anim then begin - Assert(vilefire <> nil, 'TMonster.LoadState: no vilefire anim'); - vilefire.LoadState(st, alpha, blending); + stub := TAnimState.Create(true, 2, 8); + stub.LoadState(st, alpha, blending); + stub.Invalidate; end; + FVileFireTime := gTime; // Анимации for i := ANIM_SLEEP to ANIM_PAIN do begin @@ -4305,7 +4319,7 @@ begin // Если есть - загружаем if anim then begin - Assert(FAnim[i, TDirection.D_LEFT] <> nil, 'TMonster.LoadState: no '+IntToStr(i)+'_left anim'); + Assert(FAnim[i, TDirection.D_LEFT].IsValid(), 'TMonster.LoadState: no '+IntToStr(i)+'_left anim'); FAnim[i, TDirection.D_LEFT].LoadState(st, alpha, blending); end; // Есть ли правая анимация @@ -4313,7 +4327,7 @@ begin // Если есть - загружаем if anim then begin - Assert(FAnim[i, TDirection.D_RIGHT] <> nil, 'TMonster.LoadState: no '+IntToStr(i)+'_right anim'); + Assert(FAnim[i, TDirection.D_RIGHT].IsValid(), 'TMonster.LoadState: no '+IntToStr(i)+'_right anim'); FAnim[i, TDirection.D_RIGHT].LoadState(st, alpha, blending); end; end;