moving nnext stuff plus some replacements in inactive code.

This commit is contained in:
Christoph Oelckers 2023-10-09 00:24:47 +02:00
parent 92eb20e1ad
commit 7450e82dd8
4 changed files with 230 additions and 229 deletions

View file

@ -986,125 +986,8 @@ int aiDamageSprite(DBloodActor* source, DBloodActor* actor, DAMAGE_TYPE nDmgType
#ifdef NOONE_EXTENSIONS #ifdef NOONE_EXTENSIONS
if (gModernMap) { if (gModernMap) {
int dmg = nnextCheckPatrol(source, actor, nDmgType, nDamage);
// for enemies in patrol mode if (dmg > -1) return dmg;
if (aiInPatrolState(actor->xspr.aiState))
{
aiPatrolStop(actor, source, actor->xspr.dudeAmbush);
auto pPlayer = getPlayer(source->GetType());
if (!pPlayer) return nDamage;
//if (powerupCheck(pPlayer, kPwUpShadowCloak)) pPlayer->pwUpTime[kPwUpShadowCloak] = 0;
if (readyForCrit(source, actor))
{
nDamage += aiDamageSprite(actor, source, nDmgType, nDamage * (10 - gGameOptions.nDifficulty));
if (actor->xspr.health > 0)
{
int fullHp = (actor->xspr.sysData2 > 0) ? ClipRange(actor->xspr.sysData2 << 4, 1, 65535) : getDudeInfo(actor)->startHealth << 4;
if (((100 * actor->xspr.health) / fullHp) <= 75)
{
actor->cumulDamage += nDamage << 4; // to be sure any enemy will play the recoil animation
RecoilDude(actor);
}
}
DPrintf(DMSG_SPAMMY, "Player #%d does the critical damage to patrol dude #%d!", pPlayer->pnum + 1, actor->GetIndex());
}
return nDamage;
}
if (actor->GetType() == kDudeModernCustomBurning)
{
if (Chance(0x2000) && actor->dudeExtra.time < PlayClock) {
playGenDudeSound(actor,kGenDudeSndBurning);
actor->dudeExtra.time = PlayClock + 360;
}
if (actor->xspr.burnTime == 0) actor->xspr.burnTime = 2400;
if (spriteIsUnderwater(actor, false))
{
actor->ChangeType(kDudeModernCustom);
actor->xspr.burnTime = 0;
actor->xspr.health = 1; // so it can be killed with flame weapons while underwater and if already was burning dude before.
aiGenDudeNewState(actor, &genDudeGotoW);
}
return nDamage;
}
if (actor->GetType() == kDudeModernCustom)
{
GENDUDEEXTRA* pExtra = &actor->genDudeExtra;
if (nDmgType == kDamageBurn)
{
if (actor->xspr.health > (uint32_t)pDudeInfo->fleeHealth) return nDamage;
else if (actor->xspr.txID <= 0 || getNextIncarnation(actor) == nullptr)
{
removeDudeStuff(actor);
if (pExtra->weaponType == kGenDudeWeaponKamikaze)
doExplosion(actor, actor->xspr.data1 - kTrapExploder);
if (spriteIsUnderwater(actor))
{
actor->xspr.health = 0;
return nDamage;
}
if (actor->xspr.burnTime <= 0)
actor->xspr.burnTime = 1200;
if (pExtra->canBurn && pExtra->availDeaths[kDamageBurn] > 0) {
aiPlay3DSound(actor, 361, AI_SFX_PRIORITY_0, -1);
playGenDudeSound(actor,kGenDudeSndBurning);
actor->ChangeType(kDudeModernCustomBurning);
if (actor->xspr.data2 == kGenDudeDefaultSeq) // don't inherit palette for burning if using default animation
actor->spr.pal = 0;
aiGenDudeNewState(actor, &genDudeBurnGoto);
actHealDude(actor, dudeInfo[55].startHealth, dudeInfo[55].startHealth);
actor->dudeExtra.time = PlayClock + 360;
evKillActor(actor, AF(fxFlameLick));
}
}
else
{
actKillDude(actor, actor, kDamageFall, 65535);
}
}
else if (canWalk(actor) && !inDodge(actor->xspr.aiState) && !inRecoil(actor->xspr.aiState))
{
if (!dudeIsMelee(actor))
{
if (inIdle(actor->xspr.aiState) || Chance(getDodgeChance(actor)))
{
if (!spriteIsUnderwater(actor))
{
if (!canDuck(actor) || !dudeIsPlayingSeq(actor, 14)) aiGenDudeNewState(actor, &genDudeDodgeShortL);
else aiGenDudeNewState(actor, &genDudeDodgeShortD);
if (Chance(0x0200))
playGenDudeSound(actor,kGenDudeSndGotHit);
}
else if (dudeIsPlayingSeq(actor, 13))
{
aiGenDudeNewState(actor, &genDudeDodgeShortW);
}
}
}
else if (Chance(0x0200))
{
playGenDudeSound(actor,kGenDudeSndGotHit);
}
}
return nDamage;
}
} }
#endif #endif

View file

@ -187,12 +187,12 @@ void punchCallback(DBloodActor* actor)
auto const target = actor->GetTarget(); auto const target = actor->GetTarget();
if (target != nullptr) if (target != nullptr)
{ {
double nZOffset1 = getDudeInfo(actor)->eyeHeight * actor->spr.scale.Y; double nZOffset1 = actor->eyeHeight() * actor->spr.scale.Y;
double nZOffset2 = 0; double nZOffset2 = 0;
if (target->IsDudeActor()) if (target->IsDudeActor())
nZOffset2 = getDudeInfo(target)->eyeHeight * target->spr.scale.Y; nZOffset2 = target->eyeHeight() * target->spr.scale.Y;
if (!playGenDudeSound(actor, kGenDudeSndAttackMelee)) if (!playGenDudeSound(actor, kGenDudeSndAttackMelee))
sfxPlay3DSound(actor, 530, 1, 0); sfxPlay3DSound(actor, 530, 1, 0);
@ -419,7 +419,7 @@ static void unicultThinkGoto(DBloodActor* actor)
aiChooseDirection(actor, nAngle); aiChooseDirection(actor, nAngle);
// if reached target, change to search mode // if reached target, change to search mode
if (nDist < 320 && absangle(actor->spr.Angles.Yaw, nAngle) < getDudeInfo(actor)->Periphery()) if (nDist < 320 && absangle(actor->spr.Angles.Yaw, nAngle) < actor->Periphery())
{ {
if (spriteIsUnderwater(actor, false)) aiGenDudeNewState(actor, &genDudeSearchW); if (spriteIsUnderwater(actor, false)) aiGenDudeNewState(actor, &genDudeSearchW);
else aiGenDudeNewState(actor, &genDudeSearchL); else aiGenDudeNewState(actor, &genDudeSearchL);
@ -506,11 +506,10 @@ static void unicultThinkChase(DBloodActor* actor)
} }
} }
DUDEINFO* pDudeInfo = getDudeInfo(actor);
DAngle losAngle = absangle(actor->spr.Angles.Yaw, nAngle); DAngle losAngle = absangle(actor->spr.Angles.Yaw, nAngle);
double height = (pDudeInfo->eyeHeight * actor->spr.scale.Y); double height = (actor->eyeHeight() * actor->spr.scale.Y);
if (dist > pDudeInfo->SeeDist() || !cansee(target->spr.pos, target->sector(), if (dist > actor->SeeDist() || !cansee(target->spr.pos, target->sector(),
actor->spr.pos.plusZ(-height), actor->sector())) actor->spr.pos.plusZ(-height), actor->sector()))
{ {
if (spriteIsUnderwater(actor, false)) aiGenDudeNewState(actor, &genDudeSearchW); if (spriteIsUnderwater(actor, false)) aiGenDudeNewState(actor, &genDudeSearchW);
@ -520,7 +519,7 @@ static void unicultThinkChase(DBloodActor* actor)
} }
// is the target visible? // is the target visible?
if (dist < pDudeInfo->SeeDist() && losAngle <= pDudeInfo->Periphery()) if (dist < actor->SeeDist() && losAngle <= actor->Periphery())
{ {
if ((PlayClock & 64) == 0 && Chance(0x3000) && !spriteIsUnderwater(actor, false)) if ((PlayClock & 64) == 0 && Chance(0x3000) && !spriteIsUnderwater(actor, false))
playGenDudeSound(actor, kGenDudeSndChasing); playGenDudeSound(actor, kGenDudeSndChasing);
@ -732,7 +731,7 @@ static void unicultThinkChase(DBloodActor* actor)
} }
int state = checkAttackState(actor); int state = checkAttackState(actor);
DAngle kAngle = (dudeIsMelee(actor) || dist <= 256/* kGenDudeMaxMeleeDist */) ? pDudeInfo->Periphery() : DAngle1 * 10; DAngle kAngle = (dudeIsMelee(actor) || dist <= 256/* kGenDudeMaxMeleeDist */) ? actor->Periphery() : DAngle1 * 10;
if (dist < vdist && losAngle < kAngle) if (dist < vdist && losAngle < kAngle)
{ {
@ -1069,21 +1068,20 @@ int checkAttackState(DBloodActor* actor)
static int getGenDudeMoveSpeed(DBloodActor* actor, int which, bool mul, bool shift) static int getGenDudeMoveSpeed(DBloodActor* actor, int which, bool mul, bool shift)
{ {
DUDEINFO* pDudeInfo = getDudeInfo(actor);
int speed = -1; int step = 2500; int maxSpeed = 146603; int speed = -1; int step = 2500; int maxSpeed = 146603;
switch (which) switch (which)
{ {
case 0: case 0:
speed = pDudeInfo->frontSpeed; speed = actor->FrontSpeedFixed();
break; break;
case 1: case 1:
speed = pDudeInfo->sideSpeed; speed = actor->SideSpeedFixed();
break; break;
case 2: case 2:
speed = pDudeInfo->backSpeed; speed = actor->BackSpeedFixed();
break; break;
case 3: case 3:
speed = pDudeInfo->angSpeed; speed = actor->SideSpeedFixed();
break; break;
default: default:
return -1; return -1;
@ -1109,15 +1107,14 @@ static int getGenDudeMoveSpeed(DBloodActor* actor, int which, bool mul, bool shi
void aiGenDudeMoveForward(DBloodActor* actor) void aiGenDudeMoveForward(DBloodActor* actor)
{ {
DUDEINFO* pDudeInfo = getDudeInfo(actor);
GENDUDEEXTRA* pExtra = &actor->genDudeExtra; GENDUDEEXTRA* pExtra = &actor->genDudeExtra;
if (pExtra->canFly) if (pExtra->canFly)
{ {
auto nAng = deltaangle(actor->spr.Angles.Yaw, actor->xspr.goalAng); auto nAng = deltaangle(actor->spr.Angles.Yaw, actor->xspr.goalAng);
auto nTurnRange = pDudeInfo->TurnRange(); auto nTurnRange = actor->TurnRange();
actor->spr.Angles.Yaw += clamp(nAng, -nTurnRange, nTurnRange); actor->spr.Angles.Yaw += clamp(nAng, -nTurnRange, nTurnRange);
double nAccel = pDudeInfo->FrontSpeed() * 4; double nAccel = actor->FrontSpeed() * 4;
if (abs(nAng) > DAngle60) if (abs(nAng) > DAngle60)
return; return;
if (actor->GetTarget() == nullptr) if (actor->GetTarget() == nullptr)
@ -1136,7 +1133,7 @@ void aiGenDudeMoveForward(DBloodActor* actor)
} }
else else
{ {
DAngle maxTurn = mapangle(pDudeInfo->angSpeed * 4 >> 4); DAngle maxTurn = mapangle(actor->turnAngleFixed() * 4 >> 4);
DAngle dang = actor->xspr.goalAng - actor->spr.Angles.Yaw; DAngle dang = actor->xspr.goalAng - actor->spr.Angles.Yaw;
actor->spr.Angles.Yaw += clamp(dang, -maxTurn, maxTurn); actor->spr.Angles.Yaw += clamp(dang, -maxTurn, maxTurn);
@ -1451,13 +1448,13 @@ static void scaleDamage(DBloodActor* actor)
int weaponType = actor->genDudeExtra.weaponType; int weaponType = actor->genDudeExtra.weaponType;
signed short* curScale = actor->dmgControl; signed short* curScale = actor->dmgControl;
for (int i = 0; i < kDmgMax; i++) for (int i = 0; i < kDmgMax; i++)
curScale[i] = getDudeInfo(kDudeModernCustom)->startDamage[i]; curScale[i] = actor->dmgControl[i];
switch (weaponType) { switch (weaponType) {
// just copy damage resistance of dude that should be summoned // just copy damage resistance of dude that should be summoned
case kGenDudeWeaponSummon: case kGenDudeWeaponSummon:
for (int i = 0; i < kDmgMax; i++) for (int i = 0; i < kDmgMax; i++)
curScale[i] = getDudeInfo(curWeapon)->startDamage[i]; curScale[i] = curWeapon->dmgControl[i];
break; break;
// these does not like the explosions and burning // these does not like the explosions and burning
case kGenDudeWeaponKamikaze: case kGenDudeWeaponKamikaze:
@ -1762,7 +1759,6 @@ void dudeLeechOperate(DBloodActor* actor, const EVENT& event)
double top, bottom; double top, bottom;
GetActorExtents(actor, &top, &bottom); GetActorExtents(actor, &top, &bottom);
int nType = actTarget->GetType() - kDudeBase; int nType = actTarget->GetType() - kDudeBase;
DUDEINFO* pDudeInfo = &dudeInfo[nType];
double z1 = (top - actor->spr.pos.Z) - 1; double z1 = (top - actor->spr.pos.Z) - 1;
auto atpos = actTarget->spr.pos; auto atpos = actTarget->spr.pos;
@ -1776,7 +1772,7 @@ void dudeLeechOperate(DBloodActor* actor, const EVENT& event)
actor->spr.Angles.Yaw = (atpos - actor->spr.pos.XY()).Angle(); actor->spr.Angles.Yaw = (atpos - actor->spr.pos.XY()).Angle();
DVector3 dv; DVector3 dv;
dv.XY() = actor->spr.Angles.Yaw.ToVector() * 64; dv.XY() = actor->spr.Angles.Yaw.ToVector() * 64;
double tz = actTarget->spr.pos.Z - (actTarget->spr.scale.Y * pDudeInfo->aimHeight); double tz = actTarget->spr.pos.Z - (actTarget->spr.scale.Y * actTarget->aimHeight());
double dz = (tz - top - 1) / nDist * 4; double dz = (tz - top - 1) / nDist * 4;
int nMissileType = kMissileLifeLeechAltNormal + (actor->xspr.data3 ? 1 : 0); int nMissileType = kMissileLifeLeechAltNormal + (actor->xspr.data3 ? 1 : 0);
int t2; int t2;
@ -1857,8 +1853,7 @@ DBloodActor* genDudeSpawn(DBloodActor* source, DBloodActor* actor, double nDist)
spawned->spr.Angles.Yaw = actor->spr.Angles.Yaw; spawned->spr.Angles.Yaw = actor->spr.Angles.Yaw;
SetActor(spawned, pos); SetActor(spawned, pos);
spawned->spr.cstat |= CSTAT_SPRITE_BLOCK_ALL | CSTAT_SPRITE_BLOOD_BIT1; spawned->spr.cstat |= CSTAT_SPRITE_BLOCK_ALL | CSTAT_SPRITE_BLOOD_BIT1;
auto pDudeInfo = getDudeInfo(spawned); spawned->clipdist = spawned->fClipDist();
spawned->clipdist = pDudeInfo->fClipdist();
// inherit weapon, seq and sound settings. // inherit weapon, seq and sound settings.
spawned->xspr.data1 = source->xspr.data1; spawned->xspr.data1 = source->xspr.data1;
@ -1877,7 +1872,7 @@ DBloodActor* genDudeSpawn(DBloodActor* source, DBloodActor* actor, double nDist)
spawned->copy_clipdist(source); spawned->copy_clipdist(source);
// inherit custom hp settings // inherit custom hp settings
if (source->xspr.data4 <= 0) spawned->xspr.health = pDudeInfo->startHealth << 4; if (source->xspr.data4 <= 0) spawned->xspr.health = actor->startHealth() << 4;
else spawned->xspr.health = ClipRange(source->xspr.data4 << 4, 1, 65535); else spawned->xspr.health = ClipRange(source->xspr.data4 << 4, 1, 65535);
@ -1996,10 +1991,10 @@ void genDudeTransform(DBloodActor* actor)
actIncarnation->xspr.key = actIncarnation->xspr.dropMsg = 0; actIncarnation->xspr.key = actIncarnation->xspr.dropMsg = 0;
// set hp // set hp
if (actor->xspr.sysData2 <= 0) actor->xspr.health = dudeInfo[actor->GetType() - kDudeBase].startHealth << 4; if (actor->xspr.sysData2 <= 0) actor->xspr.health = actor->startHealth() << 4;
else actor->xspr.health = ClipRange(actor->xspr.sysData2 << 4, 1, 65535); else actor->xspr.health = ClipRange(actor->xspr.sysData2 << 4, 1, 65535);
int seqId = dudeInfo[actor->GetType() - kDudeBase].seqStartID; int seqId = actor->seqStartID();
switch (actor->GetType()) { switch (actor->GetType()) {
case kDudePodMother: // fake dude case kDudePodMother: // fake dude
case kDudeTentacleMother: // fake dude case kDudeTentacleMother: // fake dude
@ -2301,7 +2296,7 @@ bool genDudePrepare(DBloodActor* actor, int propId)
// check the animation // check the animation
int seqStartId = -1; int seqStartId = -1;
if (actor->xspr.data2 <= 0) seqStartId = actor->xspr.data2 = getDudeInfo(actor)->seqStartID; if (actor->xspr.data2 <= 0) seqStartId = actor->xspr.data2 = actor->seqStartID();
else seqStartId = actor->xspr.data2; else seqStartId = actor->xspr.data2;
for (int i = seqStartId; i < seqStartId + kGenDudeSeqMax; i++) { for (int i = seqStartId; i < seqStartId + kGenDudeSeqMax; i++) {
@ -2315,7 +2310,7 @@ bool genDudePrepare(DBloodActor* actor, int propId)
Seq* pSeq = getSequence(i); Seq* pSeq = getSequence(i);
if (!pSeq) if (!pSeq)
{ {
actor->xspr.data2 = getDudeInfo(actor)->seqStartID; actor->xspr.data2 = actor->seqStartID();
viewSetSystemMessage("No SEQ animation id %d found for custom dude #%d!", i, actor->GetIndex()); viewSetSystemMessage("No SEQ animation id %d found for custom dude #%d!", i, actor->GetIndex());
viewSetSystemMessage("SEQ base id: %d", seqStartId); viewSetSystemMessage("SEQ base id: %d", seqStartId);
} }
@ -2543,7 +2538,7 @@ bool actKillModernDude(DBloodActor* actor, DAMAGE_TYPE damageType)
actor->spr.pal = 0; actor->spr.pal = 0;
aiGenDudeNewState(actor, &genDudeBurnGoto); aiGenDudeNewState(actor, &genDudeBurnGoto);
actHealDude(actor, dudeInfo[55].startHealth, dudeInfo[55].startHealth); actHealDude(actor, actor->startHealth(), actor->startHealth());
if (actor->xspr.burnTime <= 0) actor->xspr.burnTime = 1200; if (actor->xspr.burnTime <= 0) actor->xspr.burnTime = 1200;
actor->dudeExtra.time = PlayClock + 360; actor->dudeExtra.time = PlayClock + 360;
return true; return true;

View file

@ -277,13 +277,13 @@ static DBloodActor* nnExtSpawnDude(DBloodActor* sourceactor, DBloodActor* origin
pDudeActor->spr.Angles.Yaw = angle; pDudeActor->spr.Angles.Yaw = angle;
pDudeActor->spr.cstat |= CSTAT_SPRITE_BLOOD_BIT1 | CSTAT_SPRITE_BLOCK_ALL; pDudeActor->spr.cstat |= CSTAT_SPRITE_BLOOD_BIT1 | CSTAT_SPRITE_BLOCK_ALL;
pDudeActor->clipdist = getDudeInfo(nType)->fClipdist(); pDudeActor->clipdist = pDudeActor->fClipDist();
pDudeActor->xspr.respawn = 1; pDudeActor->xspr.respawn = 1;
pDudeActor->xspr.health = getDudeInfo(nType)->startHealth << 4; pDudeActor->xspr.health = pDudeActor->startHealth() << 4;
if (fileSystem.FindResource(getDudeInfo(nType)->seqStartID, "SEQ")) if (getSequence(pDudeActor->seqStartID))
seqSpawn(getDudeInfo(nType)->seqStartID, pDudeActor); seqSpawn(pDudeActor->seqStartID, pDudeActor);
// add a way to inherit some values of spawner by dude. // add a way to inherit some values of spawner by dude.
if (sourceactor->spr.flags & kModernTypeFlag1) { if (sourceactor->spr.flags & kModernTypeFlag1) {
@ -1409,7 +1409,7 @@ int getSpriteMassBySize(DBloodActor* actor)
clipDist = actor->genDudeExtra.clipdist; clipDist = actor->genDudeExtra.clipdist;
break; break;
default: default:
seqId = getDudeInfo(actor)->seqStartID; seqId = actor->seqStartID();
break; break;
} }
} }
@ -3576,7 +3576,7 @@ void damageSprites(DBloodActor* sourceactor, DBloodActor* actor)
{ {
if (sourceactor->spr.flags & kModernTypeFlag1) dmg = ClipHigh(sourceactor->xspr.data3 << 1, 65535); if (sourceactor->spr.flags & kModernTypeFlag1) dmg = ClipHigh(sourceactor->xspr.data3 << 1, 65535);
else if (actor->xspr.sysData2 > 0) dmg = (ClipHigh(actor->xspr.sysData2 << 4, 65535) * sourceactor->xspr.data3) / kPercFull; else if (actor->xspr.sysData2 > 0) dmg = (ClipHigh(actor->xspr.sysData2 << 4, 65535) * sourceactor->xspr.data3) / kPercFull;
else dmg = ((getDudeInfo(actor)->startHealth << 4) * sourceactor->xspr.data3) / kPercFull; else dmg = ((actor->startHealth() << 4) * sourceactor->xspr.data3) / kPercFull;
health = actor->xspr.health - dmg; health = actor->xspr.health - dmg;
} }
@ -4690,7 +4690,7 @@ bool condCheckSprite(DBloodActor* aCond, int cmpOp, bool PUSH)
{ {
default: break; default: break;
case 50: // compare hp (in %) case 50: // compare hp (in %)
if (objActor->IsDudeActor()) var = (objActor->xspr.sysData2 > 0) ? ClipRange(objActor->xspr.sysData2 << 4, 1, 65535) : getDudeInfo(objActor)->startHealth << 4; if (objActor->IsDudeActor()) var = (objActor->xspr.sysData2 > 0) ? ClipRange(objActor->xspr.sysData2 << 4, 1, 65535) : objActor->startHealth() << 4;
else if (objActor->GetType() == kThingBloodChunks) return condCmp(0, arg1, arg2, cmpOp); else if (objActor->GetType() == kThingBloodChunks) return condCmp(0, arg1, arg2, cmpOp);
else if (objActor->GetType() >= kThingBase && objActor->GetType() < kThingMax) var = objActor->IntVar("defhealth") << 4; else if (objActor->GetType() >= kThingBase && objActor->GetType() < kThingMax) var = objActor->IntVar("defhealth") << 4;
return condCmp((kPercFull * objActor->xspr.health) / ClipLow(var, 1), arg1, arg2, cmpOp); return condCmp((kPercFull * objActor->xspr.health) / ClipLow(var, 1), arg1, arg2, cmpOp);
@ -5150,9 +5150,9 @@ bool aiFightDudeCanSeeTarget(DBloodActor* dudeactor, DUDEINFO* pDudeInfo, DBlood
auto dv = targetactor->spr.pos.XY() - dudeactor->spr.pos.XY(); auto dv = targetactor->spr.pos.XY() - dudeactor->spr.pos.XY();
// check target // check target
if (dv.Length() < pDudeInfo->SeeDist()) if (dv.Length() < actor->SeeDist())
{ {
double height = (pDudeInfo->eyeHeight * dudeactor->spr.scale.Y); double height = (actor->eyeHeight() * dudeactor->spr.scale.Y);
// is there a line of sight to the target? // is there a line of sight to the target?
if (cansee(dudeactor->spr.pos, dudeactor->sector(), targetactor->spr.pos.plusZ(-height), targetactor->sector())) if (cansee(dudeactor->spr.pos, dudeactor->sector(), targetactor->spr.pos.plusZ(-height), targetactor->sector()))
@ -5338,8 +5338,8 @@ int aiFightGetTargetDist(DBloodActor* actor, DUDEINFO* pDudeInfo, DBloodActor* t
auto dvec = target->spr.pos.XY() - actor->spr.pos.XY(); auto dvec = target->spr.pos.XY() - actor->spr.pos.XY();
double dist = dvec.Length(); double dist = dvec.Length();
if (dist <= pDudeInfo->MeleeDist()) return 0; if (dist <= actor->MeleeDist()) return 0;
double seeDist = pDudeInfo->SeeDist(); double seeDist = actor->SeeDist();
if (dist >= seeDist) return 13; if (dist >= seeDist) return 13;
if (dist <= seeDist / 12) return 1; if (dist <= seeDist / 12) return 1;
if (dist <= seeDist / 11) return 2; if (dist <= seeDist / 11) return 2;
@ -6009,7 +6009,7 @@ bool modernTypeOperateSprite(DBloodActor* actor, EVENT& event)
switch (cmd) { switch (cmd) {
case 36: case 36:
actHealDude(pPlayer->GetActor(), ((actor->xspr.data2 > 0) ? ClipHigh(actor->xspr.data2, 200) : getDudeInfo(pPlayer->GetActor())->startHealth), 200); actHealDude(pPlayer->GetActor(), ((actor->xspr.data2 > 0) ? ClipHigh(actor->xspr.data2, 200) : pPlayer->GetActor()->startHealth()), 200);
pPlayer->curWeapon = kWeapPitchFork; pPlayer->curWeapon = kWeapPitchFork;
break; break;
} }
@ -6961,7 +6961,7 @@ void useTargetChanger(DBloodActor* sourceactor, DBloodActor* actor)
actor->xspr.burnTime = 0; actor->xspr.burnTime = 0;
// heal dude a bit in case of friendly fire // heal dude a bit in case of friendly fire
int startHp = (actor->xspr.sysData2 > 0) ? ClipRange(actor->xspr.sysData2 << 4, 1, 65535) : pDudeInfo->startHealth << 4; int startHp = (actor->xspr.sysData2 > 0) ? ClipRange(actor->xspr.sysData2 << 4, 1, 65535) : actor->startHealth() << 4;
if (actor->xspr.health < (unsigned)startHp) actHealDude(actor, receiveHp, startHp); if (actor->xspr.health < (unsigned)startHp) actHealDude(actor, receiveHp, startHp);
} }
else if (burnactor->xspr.health <= 0) else if (burnactor->xspr.health <= 0)
@ -7032,11 +7032,11 @@ void useTargetChanger(DBloodActor* sourceactor, DBloodActor* actor)
auto mateactor = targetactor; auto mateactor = targetactor;
// heal dude // heal dude
int startHp = (actor->xspr.sysData2 > 0) ? ClipRange(actor->xspr.sysData2 << 4, 1, 65535) : pDudeInfo->startHealth << 4; int startHp = (actor->xspr.sysData2 > 0) ? ClipRange(actor->xspr.sysData2 << 4, 1, 65535) : actor->startHealth() << 4;
if (actor->xspr.health < (unsigned)startHp) actHealDude(actor, receiveHp, startHp); if (actor->xspr.health < (unsigned)startHp) actHealDude(actor, receiveHp, startHp);
// heal mate // heal mate
startHp = (mateactor->xspr.sysData2 > 0) ? ClipRange(mateactor->xspr.sysData2 << 4, 1, 65535) : getDudeInfo(mateactor)->startHealth << 4; startHp = (mateactor->xspr.sysData2 > 0) ? ClipRange(mateactor->xspr.sysData2 << 4, 1, 65535) : mateactor->startHealth() << 4;
if (mateactor->xspr.health < (unsigned)startHp) actHealDude(mateactor, receiveHp, startHp); if (mateactor->xspr.health < (unsigned)startHp) actHealDude(mateactor, receiveHp, startHp);
auto matetarget = mateactor->GetTarget(); auto matetarget = mateactor->GetTarget();
@ -8088,7 +8088,7 @@ void aiPatrolRandGoalAng(DBloodActor* actor)
void aiPatrolTurn(DBloodActor* actor) void aiPatrolTurn(DBloodActor* actor)
{ {
DAngle nTurnRange = mapangle((getDudeInfo(actor)->angSpeed << 1) >> 4); DAngle nTurnRange = mapangle((actor->angSpeed << 1) >> 4);
DAngle nAng = deltaangle(actor->spr.Angles.Yaw, actor->xspr.goalAng); DAngle nAng = deltaangle(actor->spr.Angles.Yaw, actor->xspr.goalAng);
actor->spr.Angles.Yaw += clamp(nAng, -nTurnRange, nTurnRange); actor->spr.Angles.Yaw += clamp(nAng, -nTurnRange, nTurnRange);
@ -8119,10 +8119,9 @@ void aiPatrolMove(DBloodActor* actor)
break; break;
} }
DUDEINFO* pDudeInfo = &dudeInfo[dudeIdx];
const DUDEINFO_EXTRA* pExtra = &gDudeInfoExtra[dudeIdx]; const DUDEINFO_EXTRA* pExtra = &gDudeInfoExtra[dudeIdx];
DVector3 dv = targetactor->spr.pos - actor->spr.pos.plusZ(-pDudeInfo->eyeHeight); // eyeHeight is in map units! DVector3 dv = targetactor->spr.pos - actor->spr.pos.plusZ(-actor->eyeHeight()); // eyeHeight is in map units!
DAngle goalAng = DAngle180 / 3; DAngle goalAng = DAngle180 / 3;
@ -8138,7 +8137,7 @@ void aiPatrolMove(DBloodActor* actor)
actor->spr.flags |= kPhysGravity | kPhysFalling; actor->spr.flags |= kPhysGravity | kPhysFalling;
} }
DAngle nTurnRange = pDudeInfo->TurnRange() / 64; DAngle nTurnRange = actor->TurnRange() / 64;
DAngle nAng = deltaangle(actor->spr.Angles.Yaw, actor->xspr.goalAng); DAngle nAng = deltaangle(actor->spr.Angles.Yaw, actor->xspr.goalAng);
actor->spr.Angles.Yaw += clamp(nAng, -nTurnRange, nTurnRange); actor->spr.Angles.Yaw += clamp(nAng, -nTurnRange, nTurnRange);
@ -8166,7 +8165,7 @@ void aiPatrolMove(DBloodActor* actor)
} }
else else
{ {
int frontSpeed = pDudeInfo->frontSpeed; int frontSpeed = actor->FrontSpeedFixed();
switch (actor->GetType()) switch (actor->GetType())
{ {
case kDudeModernCustom: case kDudeModernCustom:
@ -8175,7 +8174,7 @@ void aiPatrolMove(DBloodActor* actor)
break; break;
} }
frontSpeed = aiPatrolGetVelocity(pDudeInfo->frontSpeed, targetactor->xspr.busyTime); frontSpeed = aiPatrolGetVelocity(actor->FrontSpeedFixed(), targetactor->xspr.busyTime);
actor->vel += actor->spr.Angles.Yaw.ToVector() * FixedToFloat(frontSpeed); actor->vel += actor->spr.Angles.Yaw.ToVector() * FixedToFloat(frontSpeed);
} }
@ -8213,7 +8212,7 @@ void aiPatrolAlarmLite(DBloodActor* actor, DBloodActor* targetactor)
if (dudeactor->xspr.health <= 0) if (dudeactor->xspr.health <= 0)
continue; continue;
double eaz2 = (getDudeInfo(targetactor)->eyeHeight * targetactor->spr.scale.Y); double eaz2 = (targetactor->eyeHeight() * targetactor->spr.scale.Y);
double nDist = (dudeactor->spr.pos.XY() - actor->spr.pos.XY()).LengthSquared(); double nDist = (dudeactor->spr.pos.XY() - actor->spr.pos.XY()).LengthSquared();
if (nDist >= kPatrolAlarmSeeDistSq || !cansee(DVector3(actor->spr.pos.XY(), zt1), actor->sector(), dudeactor->spr.pos.plusZ(-eaz2), dudeactor->sector())) if (nDist >= kPatrolAlarmSeeDistSq || !cansee(DVector3(actor->spr.pos.XY(), zt1), actor->sector(), dudeactor->spr.pos.plusZ(-eaz2), dudeactor->sector()))
{ {
@ -8245,7 +8244,7 @@ void aiPatrolAlarmFull(DBloodActor* actor, DBloodActor* targetactor, bool chain)
if (actor->xspr.health <= 0) if (actor->xspr.health <= 0)
return; return;
double eaz2 = (getDudeInfo(actor)->eyeHeight * actor->spr.scale.Y); double eaz2 = (actor->eyeHeight() * actor->spr.scale.Y);
auto pos2 = actor->spr.pos.plusZ(-eaz2); auto pos2 = actor->spr.pos.plusZ(-eaz2);
auto pSect2 = actor->sector(); auto pSect2 = actor->sector();
@ -8265,7 +8264,7 @@ void aiPatrolAlarmFull(DBloodActor* actor, DBloodActor* targetactor, bool chain)
if (dudeactor->xspr.health <= 0) if (dudeactor->xspr.health <= 0)
continue; continue;
double eaz1 = (getDudeInfo(dudeactor)->eyeHeight * dudeactor->spr.scale.Y); double eaz1 = (dudeactor->eyeHeight() * dudeactor->spr.scale.Y);
auto pos1 = dudeactor->spr.pos.plusZ(-eaz1); auto pos1 = dudeactor->spr.pos.plusZ(-eaz1);
auto pSect1 = dudeactor->sector(); auto pSect1 = dudeactor->sector();
@ -8362,7 +8361,7 @@ DBloodActor* aiPatrolSearchTargets(DBloodActor* actor)
PATROL_FOUND_SOUNDS patrolBonkles[kMaxPatrolFoundSounds]; PATROL_FOUND_SOUNDS patrolBonkles[kMaxPatrolFoundSounds];
assert(actor->IsDudeActor()); assert(actor->IsDudeActor());
DUDEINFO* pDudeInfo = getDudeInfo(actor); DBloodPlayer* pPlayer = NULL; DBloodPlayer* pPlayer = NULL;
for (int i = 0; i < kMaxPatrolFoundSounds; i++) for (int i = 0; i < kMaxPatrolFoundSounds; i++)
{ {
@ -8393,8 +8392,8 @@ DBloodActor* aiPatrolSearchTargets(DBloodActor* actor)
auto pos = plActor->spr.pos; auto pos = plActor->spr.pos;
auto dv = pos.XY() - actor->spr.pos.XY(); auto dv = pos.XY() - actor->spr.pos.XY();
double nDistf = dv.Length(); double nDistf = dv.Length();
double seeDistf = (stealth) ? pDudeInfo->SeeDist() / 3 : pDudeInfo->SeeDist() / 4; double seeDistf = (stealth) ? actor->SeeDist() / 3 : actor->SeeDist() / 4;
double hearDistf = pDudeInfo->HearDist(); double hearDistf = actor->HearDist();
double feelDistf = hearDistf / 2; double feelDistf = hearDistf / 2;
// TO-DO: is there any dudes that sees this patrol dude and sees target? // TO-DO: is there any dudes that sees this patrol dude and sees target?
@ -8403,7 +8402,7 @@ DBloodActor* aiPatrolSearchTargets(DBloodActor* actor)
if (nDistf <= seeDistf) if (nDistf <= seeDistf)
{ {
double scratch; double scratch;
double eyeAboveZ = (pDudeInfo->eyeHeight * actor->spr.scale.Y); double eyeAboveZ = (actor->eyeHeight() * actor->spr.scale.Y);
if (nDistf < seeDistf / 8) GetActorExtents(pPlayer->GetActor(), &pos.Z, &scratch); //use ztop of the target sprite if (nDistf < seeDistf / 8) GetActorExtents(pPlayer->GetActor(), &pos.Z, &scratch); //use ztop of the target sprite
if (!cansee(pos, plActor->sector(), actor->spr.pos - eyeAboveZ, actor->sector())) if (!cansee(pos, plActor->sector(), actor->spr.pos - eyeAboveZ, actor->sector()))
continue; continue;
@ -8542,7 +8541,7 @@ DBloodActor* aiPatrolSearchTargets(DBloodActor* actor)
if (seeDistf) if (seeDistf)
{ {
DAngle periphery = max(pDudeInfo->Periphery(), DAngle60); DAngle periphery = max(actor->Periphery(), DAngle60);
DAngle nDeltaAngle = absangle(actor->spr.Angles.Yaw, dv.Angle()); DAngle nDeltaAngle = absangle(actor->spr.Angles.Yaw, dv.Angle());
if ((itCanSee = (!blind && nDistf < seeDistf && nDeltaAngle < periphery)) == true) if ((itCanSee = (!blind && nDistf < seeDistf && nDeltaAngle < periphery)) == true)
{ {
@ -9284,6 +9283,129 @@ void killEffectGenCallbacks(DBloodActor* actor)
} }
} }
int nnextCheckPatrol(DBloodActor* source, DBloodActor* actor, DAMAGE_TYPE nDmgType, int nDamage)
{
// for enemies in patrol mode
if (aiInPatrolState(actor->xspr.aiState))
{
aiPatrolStop(actor, source, actor->xspr.dudeAmbush);
auto pPlayer = getPlayer(source->GetType());
if (!pPlayer) return nDamage;
//if (powerupCheck(pPlayer, kPwUpShadowCloak)) pPlayer->pwUpTime[kPwUpShadowCloak] = 0;
if (readyForCrit(source, actor))
{
nDamage += aiDamageSprite(actor, source, nDmgType, nDamage * (10 - gGameOptions.nDifficulty));
if (actor->xspr.health > 0)
{
int fullHp = (actor->xspr.sysData2 > 0) ? ClipRange(actor->xspr.sysData2 << 4, 1, 65535) : actor->startHealth << 4;
if (((100 * actor->xspr.health) / fullHp) <= 75)
{
actor->cumulDamage += nDamage << 4; // to be sure any enemy will play the recoil animation
RecoilDude(actor);
}
}
DPrintf(DMSG_SPAMMY, "Player #%d does the critical damage to patrol dude #%d!", pPlayer->pnum + 1, actor->GetIndex());
}
return nDamage;
}
if (actor->GetType() == kDudeModernCustomBurning)
{
if (Chance(0x2000) && actor->dudeExtra.time < PlayClock) {
playGenDudeSound(actor,kGenDudeSndBurning);
actor->dudeExtra.time = PlayClock + 360;
}
if (actor->xspr.burnTime == 0) actor->xspr.burnTime = 2400;
if (spriteIsUnderwater(actor, false))
{
actor->ChangeType(kDudeModernCustom);
actor->xspr.burnTime = 0;
actor->xspr.health = 1; // so it can be killed with flame weapons while underwater and if already was burning dude before.
aiGenDudeNewState(actor, &genDudeGotoW);
}
return nDamage;
}
if (actor->GetType() == kDudeModernCustom)
{
GENDUDEEXTRA* pExtra = &actor->genDudeExtra;
if (nDmgType == kDamageBurn)
{
if (actor->xspr.health > (uint32_t)actor->fleeHealth()) return nDamage;
else if (actor->xspr.txID <= 0 || getNextIncarnation(actor) == nullptr)
{
removeDudeStuff(actor);
if (pExtra->weaponType == kGenDudeWeaponKamikaze)
doExplosion(actor, actor->xspr.data1 - kTrapExploder);
if (spriteIsUnderwater(actor))
{
actor->xspr.health = 0;
return nDamage;
}
if (actor->xspr.burnTime <= 0)
actor->xspr.burnTime = 1200;
if (pExtra->canBurn && pExtra->availDeaths[kDamageBurn] > 0) {
aiPlay3DSound(actor, 361, AI_SFX_PRIORITY_0, -1);
playGenDudeSound(actor,kGenDudeSndBurning);
actor->ChangeType(kDudeModernCustomBurning);
if (actor->xspr.data2 == kGenDudeDefaultSeq) // don't inherit palette for burning if using default animation
actor->spr.pal = 0;
aiGenDudeNewState(actor, &genDudeBurnGoto);
actHealDude(actor, actor->startHealth(), actor->startHealth());
actor->dudeExtra.time = PlayClock + 360;
evKillActor(actor, AF(fxFlameLick));
}
}
else
{
actKillDude(actor, actor, kDamageFall, 65535);
}
}
else if (canWalk(actor) && !inDodge(actor->xspr.aiState) && !inRecoil(actor->xspr.aiState))
{
if (!dudeIsMelee(actor))
{
if (inIdle(actor->xspr.aiState) || Chance(getDodgeChance(actor)))
{
if (!spriteIsUnderwater(actor))
{
if (!canDuck(actor) || !dudeIsPlayingSeq(actor, 14)) aiGenDudeNewState(actor, &genDudeDodgeShortL);
else aiGenDudeNewState(actor, &genDudeDodgeShortD);
if (Chance(0x0200))
playGenDudeSound(actor,kGenDudeSndGotHit);
}
else if (dudeIsPlayingSeq(actor, 13))
{
aiGenDudeNewState(actor, &genDudeDodgeShortW);
}
}
}
else if (Chance(0x0200))
{
playGenDudeSound(actor,kGenDudeSndGotHit);
}
}
return nDamage;
}
return -1;
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// //

View file

@ -78,45 +78,44 @@ void tilePrecacheTile(FTextureID nTex, int nType, int palette)
void PrecacheDude(DBloodActor* actor) void PrecacheDude(DBloodActor* actor)
{ {
int palette = actor->spr.pal; int palette = actor->spr.pal;
DUDEINFO* pDudeInfo = getDudeInfo(actor); seqPrecacheId(actor->seqStartID(), palette);
seqPrecacheId(pDudeInfo->seqStartID, palette); seqPrecacheId(actor->seqStartID() + 5, palette);
seqPrecacheId(pDudeInfo->seqStartID + 5, palette); seqPrecacheId(actor->seqStartID() + 1, palette);
seqPrecacheId(pDudeInfo->seqStartID + 1, palette); seqPrecacheId(actor->seqStartID() + 2, palette);
seqPrecacheId(pDudeInfo->seqStartID + 2, palette);
switch (actor->GetType()) switch (actor->GetType())
{ {
case kDudeCultistTommy: case kDudeCultistTommy:
case kDudeCultistShotgun: case kDudeCultistShotgun:
case kDudeCultistTesla: case kDudeCultistTesla:
case kDudeCultistTNT: case kDudeCultistTNT:
seqPrecacheId(pDudeInfo->seqStartID + 6, palette); seqPrecacheId(actor->seqStartID() + 6, palette);
seqPrecacheId(pDudeInfo->seqStartID + 7, palette); seqPrecacheId(actor->seqStartID() + 7, palette);
seqPrecacheId(pDudeInfo->seqStartID + 8, palette); seqPrecacheId(actor->seqStartID() + 8, palette);
seqPrecacheId(pDudeInfo->seqStartID + 9, palette); seqPrecacheId(actor->seqStartID() + 9, palette);
seqPrecacheId(pDudeInfo->seqStartID + 13, palette); seqPrecacheId(actor->seqStartID() + 13, palette);
seqPrecacheId(pDudeInfo->seqStartID + 14, palette); seqPrecacheId(actor->seqStartID() + 14, palette);
seqPrecacheId(pDudeInfo->seqStartID + 15, palette); seqPrecacheId(actor->seqStartID() + 15, palette);
break; break;
case kDudeZombieButcher: case kDudeZombieButcher:
case kDudeGillBeast: case kDudeGillBeast:
seqPrecacheId(pDudeInfo->seqStartID + 6, palette); seqPrecacheId(actor->seqStartID() + 6, palette);
seqPrecacheId(pDudeInfo->seqStartID + 7, palette); seqPrecacheId(actor->seqStartID() + 7, palette);
seqPrecacheId(pDudeInfo->seqStartID + 8, palette); seqPrecacheId(actor->seqStartID() + 8, palette);
seqPrecacheId(pDudeInfo->seqStartID + 9, palette); seqPrecacheId(actor->seqStartID() + 9, palette);
seqPrecacheId(pDudeInfo->seqStartID + 10, palette); seqPrecacheId(actor->seqStartID() + 10, palette);
seqPrecacheId(pDudeInfo->seqStartID + 11, palette); seqPrecacheId(actor->seqStartID() + 11, palette);
break; break;
case kDudeGargoyleStatueFlesh: case kDudeGargoyleStatueFlesh:
case kDudeGargoyleStatueStone: case kDudeGargoyleStatueStone:
seqPrecacheId(pDudeInfo->seqStartID + 6, palette); seqPrecacheId(actor->seqStartID() + 6, palette);
seqPrecacheId(pDudeInfo->seqStartID + 6, palette); //??? seqPrecacheId(actor->seqStartID() + 6, palette); //???
[[fallthrough]]; [[fallthrough]];
case kDudeGargoyleFlesh: case kDudeGargoyleFlesh:
case kDudeGargoyleStone: case kDudeGargoyleStone:
seqPrecacheId(pDudeInfo->seqStartID + 6, palette); seqPrecacheId(actor->seqStartID() + 6, palette);
seqPrecacheId(pDudeInfo->seqStartID + 7, palette); seqPrecacheId(actor->seqStartID() + 7, palette);
seqPrecacheId(pDudeInfo->seqStartID + 8, palette); seqPrecacheId(actor->seqStartID() + 8, palette);
seqPrecacheId(pDudeInfo->seqStartID + 9, palette); seqPrecacheId(actor->seqStartID() + 9, palette);
break; break;
case kDudePhantasm: case kDudePhantasm:
case kDudeHellHound: case kDudeHellHound:
@ -125,38 +124,38 @@ void PrecacheDude(DBloodActor* actor)
case kDudeSpiderBlack: case kDudeSpiderBlack:
case kDudeSpiderMother: case kDudeSpiderMother:
case kDudeTchernobog: case kDudeTchernobog:
seqPrecacheId(pDudeInfo->seqStartID + 6, palette); seqPrecacheId(actor->seqStartID() + 6, palette);
seqPrecacheId(pDudeInfo->seqStartID + 7, palette); seqPrecacheId(actor->seqStartID() + 7, palette);
seqPrecacheId(pDudeInfo->seqStartID + 8, palette); seqPrecacheId(actor->seqStartID() + 8, palette);
break; break;
case kDudeCerberusTwoHead: case kDudeCerberusTwoHead:
seqPrecacheId(pDudeInfo->seqStartID + 6, palette); seqPrecacheId(actor->seqStartID() + 6, palette);
seqPrecacheId(pDudeInfo->seqStartID + 7, palette); seqPrecacheId(actor->seqStartID() + 7, palette);
[[fallthrough]]; [[fallthrough]];
case kDudeHand: case kDudeHand:
case kDudeBoneEel: case kDudeBoneEel:
case kDudeBat: case kDudeBat:
case kDudeRat: case kDudeRat:
seqPrecacheId(pDudeInfo->seqStartID + 6, palette); seqPrecacheId(actor->seqStartID() + 6, palette);
seqPrecacheId(pDudeInfo->seqStartID + 7, palette); seqPrecacheId(actor->seqStartID() + 7, palette);
break; break;
case kDudeCultistBeast: case kDudeCultistBeast:
seqPrecacheId(pDudeInfo->seqStartID + 6, palette); seqPrecacheId(actor->seqStartID() + 6, palette);
break; break;
case kDudeZombieAxeBuried: case kDudeZombieAxeBuried:
seqPrecacheId(pDudeInfo->seqStartID + 12, palette); seqPrecacheId(actor->seqStartID() + 12, palette);
seqPrecacheId(pDudeInfo->seqStartID + 9, palette); seqPrecacheId(actor->seqStartID() + 9, palette);
[[fallthrough]]; [[fallthrough]];
case kDudeZombieAxeLaying: case kDudeZombieAxeLaying:
seqPrecacheId(pDudeInfo->seqStartID + 10, palette); seqPrecacheId(actor->seqStartID() + 10, palette);
[[fallthrough]]; [[fallthrough]];
case kDudeZombieAxeNormal: case kDudeZombieAxeNormal:
seqPrecacheId(pDudeInfo->seqStartID + 6, palette); seqPrecacheId(actor->seqStartID() + 6, palette);
seqPrecacheId(pDudeInfo->seqStartID + 7, palette); seqPrecacheId(actor->seqStartID() + 7, palette);
seqPrecacheId(pDudeInfo->seqStartID + 8, palette); seqPrecacheId(actor->seqStartID() + 8, palette);
seqPrecacheId(pDudeInfo->seqStartID + 11, palette); seqPrecacheId(actor->seqStartID() + 11, palette);
seqPrecacheId(pDudeInfo->seqStartID + 13, palette); seqPrecacheId(actor->seqStartID() + 13, palette);
seqPrecacheId(pDudeInfo->seqStartID + 14, palette); seqPrecacheId(actor->seqStartID() + 14, palette);
break; break;
} }
} }
@ -237,17 +236,19 @@ void PreloadCache()
tilePrecacheTile(aTexIds[kTexBLOODDRIP], -1, 0); // blood drip tilePrecacheTile(aTexIds[kTexBLOODDRIP], -1, 0); // blood drip
// Player SEQs // Player SEQs
seqPrecacheId(dudeInfo[31].seqStartID + 6, 0); auto playerdef = static_cast<DBloodActor*>(GetDefaultByType(PClass::FindActor("BloodPlayerBase")));
seqPrecacheId(dudeInfo[31].seqStartID + 7, 0); int seqStartID = playerdef->seqStartID();
seqPrecacheId(dudeInfo[31].seqStartID + 8, 0); seqPrecacheId(seqStartID + 6, 0);
seqPrecacheId(dudeInfo[31].seqStartID + 9, 0); seqPrecacheId(seqStartID + 7, 0);
seqPrecacheId(dudeInfo[31].seqStartID + 10, 0); seqPrecacheId(seqStartID + 8, 0);
seqPrecacheId(dudeInfo[31].seqStartID + 14, 0); seqPrecacheId(seqStartID + 9, 0);
seqPrecacheId(dudeInfo[31].seqStartID + 15, 0); seqPrecacheId(seqStartID + 10, 0);
seqPrecacheId(dudeInfo[31].seqStartID + 12, 0); seqPrecacheId(seqStartID + 14, 0);
seqPrecacheId(dudeInfo[31].seqStartID + 16, 0); seqPrecacheId(seqStartID + 15, 0);
seqPrecacheId(dudeInfo[31].seqStartID + 17, 0); seqPrecacheId(seqStartID + 12, 0);
seqPrecacheId(dudeInfo[31].seqStartID + 18, 0); seqPrecacheId(seqStartID + 16, 0);
seqPrecacheId(seqStartID + 17, 0);
seqPrecacheId(seqStartID + 18, 0);
/* fixme: cache the composite sky. These are useless. /* fixme: cache the composite sky. These are useless.
for (auto& sect : sector) for (auto& sect : sector)