precaching abstraction.

Due to the use of SEQ IDs this is a bit ugly, with named SEQs the whole thing is more straightforward.
This commit is contained in:
Christoph Oelckers 2023-10-11 19:38:49 +02:00
parent 9eef6c42cb
commit 5ed69f4965
4 changed files with 130 additions and 166 deletions

View file

@ -856,4 +856,19 @@ DEFINE_SCRIPTED_PROPERTY(gibtype, III, BloodDudeBase)
} }
// store all data in a single array.
TArray<int> preloadseqs; // this is only useful for sequence IDs.
DEFINE_PROPERTY(preloadseq, iiiiiiiiiiiiiiii, BloodActor)
{
auto start = preloadseqs.Reserve(PROP_PARM_COUNT);
for (int i = 0; i < PROP_PARM_COUNT; i++)
{
PROP_INT_PARM(v3, i);
preloadseqs[start + i] = v3;
}
info->ActorInfo()->FirstAction = start;
info->ActorInfo()->NumActions = PROP_PARM_COUNT;
}
END_BLD_NS END_BLD_NS

View file

@ -1,25 +1,20 @@
//-------------------------------------------------------------------------
/* /*
Copyright (C) 2010-2019 EDuke32 developers and contributors * Copyright (C) 2018, 2022 nukeykt
Copyright (C) 2019 Nuke.YKT * Copyright (C) 2020-2023 Christoph Oelckers
*
This file is part of NBlood. * This file is part of Raze
*
NBlood is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License version 2 * modify it under the terms of the GNU General Public License
as published by the Free Software Foundation. * as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, *
but WITHOUT ANY WARRANTY; without even the implied warranty of * This program is distributed in the hope that it will be useful,
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
See the GNU General Public License for more details. * GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License */
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
//-------------------------------------------------------------------------
#include "ns.h" // Must come before everything else! #include "ns.h" // Must come before everything else!
#include "build.h" #include "build.h"
@ -30,8 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS BEGIN_BLD_NS
int nPrecacheCount;
void fxPrecache(); void fxPrecache();
void gibPrecache(); void gibPrecache();
@ -48,18 +41,10 @@ void tilePrecacheTile(FTextureID nTex, int nType, int palette)
if (!nTex.isValid()) return; if (!nTex.isValid()) return;
switch (GetExtInfo(nTex).picanm.extra & 7) switch (GetExtInfo(nTex).picanm.extra & 7)
{ {
case 0: case 1: n = 5; break;
n = 1; case 2: n = 8; break;
break; case 3: n = 2; break;
case 1: default: break;
n = 5;
break;
case 2:
n = 8;
break;
case 3:
n = 2;
break;
} }
while (n--) while (n--)
{ {
@ -75,88 +60,49 @@ void tilePrecacheTile(FTextureID nTex, int nType, int palette)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
extern TArray<int> preloadseqs; // this is only useful for sequence IDs.
void PrecacheDude(DBloodActor* actor) void PrecacheDude(DBloodActor* actor)
{ {
auto cls = actor->GetClass();
auto seqname = actor->seqStartName();
int seqstart = actor->seqStartID();
int palette = actor->spr.pal; int palette = actor->spr.pal;
seqPrecacheId(actor->seqStartName(), actor->seqStartID(), palette); if (seqname == NAME_None)
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 5, palette);
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 1, palette);
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 2, palette);
switch (actor->GetType())
{ {
case kDudeCultistTommy: if (seqstart > 0)
case kDudeCultistShotgun: {
case kDudeCultistTesla: while (cls->IsDescendantOf(BloodDudeBaseClass))
case kDudeCultistTNT: {
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 6, palette); auto firstindex = static_cast<PClassActor*>(cls)->ActorInfo()->FirstAction;
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 7, palette); auto numseqs = static_cast<PClassActor*>(cls)->ActorInfo()->NumActions;
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 8, palette); for (int i = 0; i < numseqs; i++)
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 9, palette); {
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 13, palette); seqPrecacheId(NAME_None, seqstart + preloadseqs[i], palette);
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 14, palette); }
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 15, palette); cls = cls->ParentClass;
break; }
case kDudeZombieButcher: }
case kDudeGillBeast: }
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 6, palette); else
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 7, palette); {
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 8, palette); auto firstindex = static_cast<PClassActor*>(cls)->ActorInfo()->FirstAction;
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 9, palette); auto numseqs = static_cast<PClassActor*>(cls)->ActorInfo()->NumActions;
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 10, palette); if (numseqs > 0)
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 11, palette); {
break; for (int i = 0; i < numseqs; i++)
case kDudeGargoyleStatueFlesh: {
case kDudeGargoyleStatueStone: seqPrecacheId(seqname, preloadseqs[i], palette);
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 6, palette); }
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 6, palette); //??? }
[[fallthrough]]; else
case kDudeGargoyleFlesh: {
case kDudeGargoyleStone: for (int i = 0; i < 100; i++) // cache everything with the given name.
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 6, palette); {
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 7, palette); seqPrecacheId(seqname, i, palette);
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 8, palette); }
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 9, palette); }
break;
case kDudePhantasm:
case kDudeHellHound:
case kDudeSpiderBrown:
case kDudeSpiderRed:
case kDudeSpiderBlack:
case kDudeSpiderMother:
case kDudeTchernobog:
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 6, palette);
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 7, palette);
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 8, palette);
break;
case kDudeCerberusTwoHead:
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 6, palette);
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 7, palette);
[[fallthrough]];
case kDudeHand:
case kDudeBoneEel:
case kDudeBat:
case kDudeRat:
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 6, palette);
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 7, palette);
break;
case kDudeCultistBeast:
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 6, palette);
break;
case kDudeZombieAxeBuried:
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 12, palette);
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 9, palette);
[[fallthrough]];
case kDudeZombieAxeLaying:
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 10, palette);
[[fallthrough]];
case kDudeZombieAxeNormal:
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 6, palette);
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 7, palette);
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 8, palette);
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 11, palette);
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 13, palette);
seqPrecacheId(actor->seqStartName(), actor->seqStartID() + 14, palette);
break;
} }
} }
@ -168,30 +114,21 @@ void PrecacheDude(DBloodActor* actor)
void PrecacheThing(DBloodActor* actor) void PrecacheThing(DBloodActor* actor)
{ {
auto cls = actor->GetClass();
auto seqname = actor->seqStartName();
int palette = actor->spr.pal; int palette = actor->spr.pal;
switch (actor->GetType()) { if (seqname == NAME_None)
case kThingGlassWindow: // worthless... {
case kThingFluorescent: while (cls->IsDescendantOf(BloodThingBaseClass))
seqPrecacheId(12, palette); {
break; auto firstindex = static_cast<PClassActor*>(cls)->ActorInfo()->FirstAction;
case kThingSpiderWeb: auto numseqs = static_cast<PClassActor*>(cls)->ActorInfo()->NumActions;
seqPrecacheId(15, palette); for (int i = 0; i < numseqs; i++)
break; {
case kThingMetalGrate: seqPrecacheId(NAME_None, preloadseqs[i], palette);
seqPrecacheId(21, palette); }
break; cls = cls->ParentClass;
case kThingFlammableTree: }
seqPrecacheId(25, palette);
seqPrecacheId(26, palette);
break;
case kTrapMachinegun:
seqPrecacheId(38, palette);
seqPrecacheId(40, palette);
seqPrecacheId(28, palette);
break;
case kThingObjectGib:
//case kThingObjectExplode: weird that only gib object is precached and this one is not
break;
} }
tilePrecacheTile(actor->spr.spritetexture(), -1, palette); tilePrecacheTile(actor->spr.spritetexture(), -1, palette);
} }
@ -226,10 +163,10 @@ void PreloadCache()
} }
} }
// Precache common SEQs // On modern systems it makes sense to precache all of the common SEQs unconditionally.
for (int i = 0; i < 100; i++) for (int i = 0; i < 100; i++)
{ {
seqPrecacheId(i, 0); seqPrecacheId(NAME_None, i, 0);
} }
tilePrecacheTile(aTexIds[kTexWATERDRIP], -1, 0); // water drip tilePrecacheTile(aTexIds[kTexWATERDRIP], -1, 0); // water drip
@ -238,30 +175,19 @@ void PreloadCache()
// Player SEQs // Player SEQs
auto playerdef = static_cast<DBloodActor*>(GetDefaultByType(PClass::FindActor("BloodPlayerBase"))); auto playerdef = static_cast<DBloodActor*>(GetDefaultByType(PClass::FindActor("BloodPlayerBase")));
int seqStartID = playerdef->seqStartID(); int seqStartID = playerdef->seqStartID();
seqPrecacheId(seqStartID + 6, 0); seqPrecacheId(NAME_None, seqStartID + 6, 0);
seqPrecacheId(seqStartID + 7, 0); seqPrecacheId(NAME_None, seqStartID + 7, 0);
seqPrecacheId(seqStartID + 8, 0); seqPrecacheId(NAME_None, seqStartID + 8, 0);
seqPrecacheId(seqStartID + 9, 0); seqPrecacheId(NAME_None, seqStartID + 9, 0);
seqPrecacheId(seqStartID + 10, 0); seqPrecacheId(NAME_None, seqStartID + 10, 0);
seqPrecacheId(seqStartID + 14, 0); seqPrecacheId(NAME_None, seqStartID + 14, 0);
seqPrecacheId(seqStartID + 15, 0); seqPrecacheId(NAME_None, seqStartID + 15, 0);
seqPrecacheId(seqStartID + 12, 0); seqPrecacheId(NAME_None, seqStartID + 12, 0);
seqPrecacheId(seqStartID + 16, 0); seqPrecacheId(NAME_None, seqStartID + 16, 0);
seqPrecacheId(seqStartID + 17, 0); seqPrecacheId(NAME_None, seqStartID + 17, 0);
seqPrecacheId(seqStartID + 18, 0); seqPrecacheId(NAME_None, seqStartID + 18, 0);
/* fixme: cache the composite sky. These are useless. // fixme: this needs to cache the composite sky.
for (auto& sect : sector)
{
if ((sect.ceilingstat & CSTAT_SECTOR_SKY) != 0 && skyTile == -1)
skyTile = sect.ceilingtexture;
}
if (skyTile > -1 && skyTile < kMaxTiles)
{
for (int i = 1; i < gSkyCount; i++)
tilePrecacheTile(skyTile + i, 0, 0);
}
*/
WeaponPrecache(); WeaponPrecache();
fxPrecache(); fxPrecache();

View file

@ -89,11 +89,6 @@ struct SEQINST
void seqPrecacheId(FName name, int id, int palette); void seqPrecacheId(FName name, int id, int palette);
inline void seqPrecacheId(int id, int palette)
{
seqPrecacheId(NAME_None, id, palette);
}
SEQINST* GetInstance(int a1, EventObject& a2); SEQINST* GetInstance(int a1, EventObject& a2);
SEQINST* GetInstance(DBloodActor* actor); SEQINST* GetInstance(DBloodActor* actor);

View file

@ -363,6 +363,7 @@ class BloodDudeBase : Bloodactor
AISTATE "zombieFSearch", "+8", 3, 1800, null, null, aiMoveForward, zombfThinkSearch, "zombieFIdle"; AISTATE "zombieFSearch", "+8", 3, 1800, null, null, aiMoveForward, zombfThinkSearch, "zombieFIdle";
AISTATE "zombieFRecoil", "+5", 5, 0, null, null, null, null, "zombieFChase"; AISTATE "zombieFRecoil", "+5", 5, 0, null, null, null, null, "zombieFChase";
AISTATE "zombieFTeslaRecoil", "+4", 5, 0, null, null, null, null, "zombieFChase"; AISTATE "zombieFTeslaRecoil", "+4", 5, 0, null, null, null, null, "zombieFChase";
preloadseq 0, 1, 2, 5;
} }
override int getRespawnTime() override int getRespawnTime()
{ {
@ -436,6 +437,7 @@ class BloodDudeCultistTommy : BloodDudeBase
explodesound 717; explodesound 717;
+BloodDudeBase.floorhitdamage; +BloodDudeBase.floorhitdamage;
preloadseq 6, 7, 8, 9, 13, 14, 15;
} }
} }
@ -468,6 +470,7 @@ class BloodDudeCultistShotgun : BloodDudeBase
explodesound 717; explodesound 717;
+BloodDudeBase.floorhitdamage; +BloodDudeBase.floorhitdamage;
preloadseq 6, 7, 8, 9, 13, 14, 15;
} }
} }
@ -498,6 +501,7 @@ class BloodDudeZombieAxeNormal : BloodDudeBase
gibtype 15, -1, -1; gibtype 15, -1, -1;
dmgcontrol 256, 256, 112, 256, 256, 256, 160; dmgcontrol 256, 256, 112, 256, 256, 256, 160;
+BloodDudeBase.floorhitdamage; +BloodDudeBase.floorhitdamage;
preloadseq 6, 7, 8, 11, 13, 14;
} }
} }
@ -528,6 +532,7 @@ class BloodDudeZombieButcher : BloodDudeBase
gibtype 15, -1, -1; gibtype 15, -1, -1;
dmgcontrol 256, 256, 32, 128, 256, 64, 128; dmgcontrol 256, 256, 32, 128, 256, 64, 128;
+BloodDudeBase.floorhitdamage; +BloodDudeBase.floorhitdamage;
preloadseq 6, 7, 8, 9, 10, 11;
} }
} }
@ -558,6 +563,7 @@ class BloodDudeZombieAxeBuried : BloodDudeBase
gibtype 15, -1, -1; gibtype 15, -1, -1;
dmgcontrol 256, 256, 112, 256, 256, 256, 256; dmgcontrol 256, 256, 112, 256, 256, 256, 256;
+BloodDudeBase.floorhitdamage; +BloodDudeBase.floorhitdamage;
preloadseq 12, 9, 10;
} }
} }
@ -588,6 +594,7 @@ class BloodDudeGargoyleFlesh : BloodDudeBase
gibtype 30, -1, -1; gibtype 30, -1, -1;
dmgcontrol 0, 128, 48, 208, 256, 256, 256; dmgcontrol 0, 128, 48, 208, 256, 256, 256;
+BloodDudeBase.floorhitdamage; +BloodDudeBase.floorhitdamage;
preloadseq 6, 7, 8, 9;
} }
} }
@ -618,6 +625,7 @@ class BloodDudeGargoyleStone : BloodDudeBase
gibtype 19, -1, -1; gibtype 19, -1, -1;
dmgcontrol 0, 0, 10, 10, 0, 128, 64; dmgcontrol 0, 0, 10, 10, 0, 128, 64;
+BloodDudeBase.floorhitdamage; +BloodDudeBase.floorhitdamage;
preloadseq 6, 7, 8, 9;
} }
} }
@ -645,6 +653,7 @@ class BloodDudeGargoyleStatueFlesh : BloodDudeBase
backspeed 0; backspeed 0;
turnrange 0; turnrange 0;
gibtype -1, -1, -1; gibtype -1, -1, -1;
preloadseq 6, 7, 8, 9;
} }
} }
@ -672,6 +681,7 @@ class BloodDudeGargoyleStatueStone : BloodDudeBase
backspeed 0; backspeed 0;
turnrange 0; turnrange 0;
gibtype -1, -1, -1; gibtype -1, -1, -1;
preloadseq 6, 7, 8, 9;
} }
} }
@ -701,6 +711,7 @@ class BloodDudePhantasm : BloodDudeBase
gibtype -1, -1, -1; gibtype -1, -1, -1;
dmgcontrol 0, 0, 48, 0, 0, 16, 0; dmgcontrol 0, 0, 48, 0, 0, 16, 0;
+BloodDudeBase.floorhitdamage; +BloodDudeBase.floorhitdamage;
preloadseq 6, 7, 8;
} }
} }
@ -729,6 +740,7 @@ class BloodDudeHellHound : BloodDudeBase
gibtype 29, -1, -1; gibtype 29, -1, -1;
dmgcontrol 48, 0, 48, 48, 256, 128, 192; dmgcontrol 48, 0, 48, 48, 256, 128, 192;
+BloodDudeBase.floorhitdamage; +BloodDudeBase.floorhitdamage;
preloadseq 6, 7, 8;
} }
} }
@ -757,6 +769,7 @@ class BloodDudeHand : BloodDudeBase
gibtype 7, -1, -1; gibtype 7, -1, -1;
dmgcontrol 64, 256, 256, 256, 0, 64, 256; dmgcontrol 64, 256, 256, 256, 0, 64, 256;
+BloodDudeBase.floorhitdamage; +BloodDudeBase.floorhitdamage;
preloadseq 6, 7;
} }
} }
@ -786,6 +799,7 @@ class BloodDudeSpiderBrown : BloodDudeBase
gibtype 7, -1, -1; gibtype 7, -1, -1;
dmgcontrol 64, 256, 256, 96, 256, 64, 256; dmgcontrol 64, 256, 256, 96, 256, 64, 256;
+BloodDudeBase.floorhitdamage; +BloodDudeBase.floorhitdamage;
preloadseq 6, 7, 8;
} }
} }
@ -815,6 +829,7 @@ class BloodDudeSpiderRed : BloodDudeBase
gibtype 7, -1, -1; gibtype 7, -1, -1;
dmgcontrol 64, 128, 256, 96, 256, 64, 256; dmgcontrol 64, 128, 256, 96, 256, 64, 256;
+BloodDudeBase.floorhitdamage; +BloodDudeBase.floorhitdamage;
preloadseq 6, 7, 8;
} }
} }
@ -844,6 +859,7 @@ class BloodDudeSpiderBlack : BloodDudeBase
gibtype 7, -1, -1; gibtype 7, -1, -1;
dmgcontrol 128, 256, 256, 96, 256, 64, 256; dmgcontrol 128, 256, 256, 96, 256, 64, 256;
+BloodDudeBase.floorhitdamage; +BloodDudeBase.floorhitdamage;
preloadseq 6, 7, 8;
} }
} }
@ -872,6 +888,7 @@ class BloodDudeSpiderMother : BloodDudeBase
turnrange 67.5; turnrange 67.5;
gibtype 7, -1, -1; gibtype 7, -1, -1;
dmgcontrol 32, 16, 16, 16, 32, 32, 32; dmgcontrol 32, 16, 16, 16, 32, 32, 32;
preloadseq 6, 7, 8;
} }
} }
@ -902,6 +919,7 @@ class BloodDudeGillBeast : BloodDudeBase
gibtype 7, -1, -1; gibtype 7, -1, -1;
dmgcontrol 48, 80, 64, 128, 0, 128, 48; dmgcontrol 48, 80, 64, 128, 0, 128, 48;
+BloodDudeBase.floorhitdamage; +BloodDudeBase.floorhitdamage;
preloadseq 6, 7, 8, 9, 10, 11;
} }
} }
@ -930,6 +948,7 @@ class BloodDudeBoneEel : BloodDudeBase
gibtype 7, -1, -1; gibtype 7, -1, -1;
dmgcontrol 256, 256, 256, 256, 0, 256, 192; dmgcontrol 256, 256, 256, 256, 0, 256, 192;
+BloodDudeBase.floorhitdamage; +BloodDudeBase.floorhitdamage;
preloadseq 6, 7;
} }
} }
@ -958,6 +977,7 @@ class BloodDudeBat : BloodDudeBase
gibtype 7, -1, -1; gibtype 7, -1, -1;
dmgcontrol 256, 256, 256, 256, 256, 64, 256; dmgcontrol 256, 256, 256, 256, 256, 64, 256;
+BloodDudeBase.floorhitdamage; +BloodDudeBase.floorhitdamage;
preloadseq 6, 7;
} }
} }
@ -986,6 +1006,7 @@ class BloodDudeRat : BloodDudeBase
gibtype 7, -1, -1; gibtype 7, -1, -1;
dmgcontrol 256, 256, 256, 256, 256, 128, 256; dmgcontrol 256, 256, 256, 256, 256, 128, 256;
+BloodDudeBase.floorhitdamage; +BloodDudeBase.floorhitdamage;
preloadseq 6, 7;
} }
} }
@ -1174,6 +1195,7 @@ class BloodDudeCerberusTwoHead : BloodDudeBase
dmgcontrol 16, 0, 16, 16, 0, 96, 48; dmgcontrol 16, 0, 16, 16, 0, 96, 48;
deathMorphType "BloodDudeCerberusOneHead"; deathMorphType "BloodDudeCerberusOneHead";
+BloodDudeBase.floorhitdamage; +BloodDudeBase.floorhitdamage;
preloadseq 6, 7;
} }
} }
@ -1202,6 +1224,7 @@ class BloodDudeCerberusOneHead : BloodDudeBase
gibtype 7, -1, -1; gibtype 7, -1, -1;
dmgcontrol 16, 0, 16, 16, 0, 96, 48; dmgcontrol 16, 0, 16, 16, 0, 96, 48;
+BloodDudeBase.floorhitdamage; +BloodDudeBase.floorhitdamage;
preloadseq 6, 7;
} }
} }
@ -1230,6 +1253,7 @@ class BloodDudeTchernobog : BloodDudeBase
gibtype 7, -1, -1; gibtype 7, -1, -1;
dmgcontrol 3, 1, 4, 4, 0, 4, 3; dmgcontrol 3, 1, 4, 4, 0, 4, 3;
+BloodDudeBase.floorhitdamage; +BloodDudeBase.floorhitdamage;
preloadseq 6, 7, 8;
} }
} }
@ -1464,6 +1488,7 @@ class BloodDudeZombieAxeLaying : BloodDudeBase
turnrange 67.5; turnrange 67.5;
gibtype 15, -1, -1; gibtype 15, -1, -1;
dmgcontrol 256, 256, 112, 256, 256, 256, 256; dmgcontrol 256, 256, 112, 256, 256, 256, 256;
preloadseq 10;
} }
} }
@ -1555,6 +1580,7 @@ class BloodDudeCultistTesla : BloodDudeBase
dmgcontrol 256, 256, 96, 160, 256, 256, 12; dmgcontrol 256, 256, 96, 160, 256, 256, 12;
explodesound 717; explodesound 717;
preloadseq 6, 7, 8, 9, 13, 14, 15;
} }
} }
@ -1586,6 +1612,7 @@ class BloodDudeCultistTNT : BloodDudeBase
dmgcontrol 256, 160, 96, 64, 256, 256, 256; dmgcontrol 256, 160, 96, 64, 256, 256, 256;
explodesound 717; explodesound 717;
preloadseq 6, 7, 8, 9, 13, 14, 15;
} }
} }
@ -1617,6 +1644,7 @@ class BloodDudeCultistBeast : BloodDudeBase
dmgcontrol 128, 128, 16, 16, 0, 64, 48; dmgcontrol 128, 128, 16, 16, 0, 64, 48;
explodesound 717; explodesound 717;
preloadseq 6, 7;
} }
} }