work on aicdud.cpp

This commit is contained in:
Christoph Oelckers 2023-10-16 00:24:17 +02:00
parent 4f338ab8a2
commit 158cdff069
16 changed files with 1557 additions and 2800 deletions

View file

@ -656,7 +656,7 @@ set( NOT_COMPILED_SOURCE_FILES
games/blood/src/airat.cpp
games/blood/src/aispid.cpp
games/blood/src/aitchern.cpp
games/blood/src/aiunicult.cpp
games/blood/src/aicdud.cpp
games/blood/src/aizomba.cpp
games/blood/src/aizombf.cpp
games/blood/src/animatesprite.cpp

View file

@ -39,6 +39,7 @@ void MarkVerticesForSector(int sector);
static constexpr double zmaptoworld = (1 / 256.); // this for necessary conversions to convert map data to floating point representation.
static constexpr double maptoworld = (1 / 16.); // this for necessary conversions to convert map data to floating point representation.
static constexpr double REPEAT_SCALE = (1 / 64.); // map's 'repeat' values use 2.6 fixed point.
static constexpr double CLIPDIST_SCALE = 0.25;
static constexpr double INV_REPEAT_SCALE = 64;
// These are refactoring markers that should be eliminated.

View file

@ -29,7 +29,7 @@
#include "src/airat.cpp"
#include "src/aispid.cpp"
#include "src/aitchern.cpp"
#include "src/aiunicult.cpp"
#include "src/aicdud.cpp"
#include "src/aizomba.cpp"
#include "src/aizombf.cpp"
#include "src/animatesprite.cpp"

View file

@ -32,7 +32,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "blood.h"
#include "texids.h"
#ifdef NOONE_EXTENSIONS
#include "aicdud.h"
#include "nnexts.h"
#include "nnextcdud.h"
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -158,40 +158,6 @@ struct GENDUDESND
extern const GENDUDESND gCustomDudeSnd[];
// temporary, until normal DUDEEXTRA gets refactored
struct GENDUDEEXTRA
{
double clipdist;
uint16_t availDeaths[kDamageMax]; // list of seqs with deaths for each damage type
uint32_t moveSpeed;
double fireDist; // counts from sprite size
double throwDist; // counts from sprite size
uint16_t curWeapon; // data1 duplicate to avoid potential problems when changing data dynamically
uint16_t weaponType;
uint16_t baseDispersion;
uint16_t slaveCount; // how many dudes is summoned
TObjPtr<DBloodActor*> pLifeLeech; // spritenum of dropped dude's leech
TObjPtr<DBloodActor*> slave[kGenDudeMaxSlaves]; // index of the ones dude is summon
bool updReq[kGenDudePropertyMax]; // update requests
union
{
struct
{
bool sndPlaying : 1; // indicate if sound of AISTATE currently playing
bool forcePunch : 1; // indicate if there is no fire trigger in punch state seq
bool isMelee : 1;
bool canBurn : 1; // can turn in Burning dude or not
bool canElectrocute : 1;
bool canAttack : 1;
bool canRecoil : 1;
bool canWalk : 1;
bool canDuck : 1;
bool canSwim : 1;
bool canFly : 1;
};
int flags;
};
};
DBloodActor* getNextIncarnation(DBloodActor* actor);
void killDudeLeech(DBloodActor* pLeech);

View file

@ -60,14 +60,6 @@ IMPLEMENT_POINTERS_START(DBloodActor)
#ifdef NOONE_EXTENSIONS
IMPLEMENT_POINTER(prevmarker)
IMPLEMENT_POINTER(ownerActor)
IMPLEMENT_POINTER(genDudeExtra.pLifeLeech)
IMPLEMENT_POINTER(genDudeExtra.slave[0])
IMPLEMENT_POINTER(genDudeExtra.slave[1])
IMPLEMENT_POINTER(genDudeExtra.slave[2])
IMPLEMENT_POINTER(genDudeExtra.slave[3])
IMPLEMENT_POINTER(genDudeExtra.slave[4])
IMPLEMENT_POINTER(genDudeExtra.slave[5])
IMPLEMENT_POINTER(genDudeExtra.slave[6])
#endif
IMPLEMENT_POINTER(xspr.burnSource)
IMPLEMENT_POINTER(xspr.target)

View file

@ -60,6 +60,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS
// Define VM entry points for all callback functions so that we can
// a) later seamlessly call scripted functions where callbacks are used and
// b) get a means to serialize callback pointers.
// ai callbacks
DEF_ANIMATOR(aiMoveDodge)
DEF_ANIMATOR(aiMoveForward)
@ -180,11 +183,37 @@ DEF_ANIMATOR(zombaThinkSearch)
DEF_ANIMATOR(zombfThinkChase)
DEF_ANIMATOR(zombfThinkGoto)
DEF_ANIMATOR(zombfThinkSearch)
#ifdef NOONE_EXTENSIONS
// patrol
DEF_ANIMATOR(aiPatrolMove)
DEF_ANIMATOR(aiPatrolThink)
DEF_ANIMATOR(aiPatrolRandGoalAng)
DEF_ANIMATOR(aiPatrolTurn)
// custom dude
DEF_ANIMATOR(resetTarget)
DEF_ANIMATOR(moveStop)
DEF_ANIMATOR(thinkSearch)
DEF_ANIMATOR(maybeThinkSearch)
DEF_ANIMATOR(thinkChase)
DEF_ANIMATOR(thinkFlee)
DEF_ANIMATOR(thinkTarget)
DEF_ANIMATOR(thinkMorph)
DEF_ANIMATOR(thinkDying)
DEF_ANIMATOR(enterBurnSearchWater)
DEF_ANIMATOR(enterMorph)
DEF_ANIMATOR(enterDying)
DEF_ANIMATOR(enterDeath)
DEF_ANIMATOR(enterSleep)
DEF_ANIMATOR(enterWake)
DEF_ANIMATOR(turnToTarget)
DEF_ANIMATOR(moveTurn)
DEF_ANIMATOR(moveDodge)
DEF_ANIMATOR(moveForward)
DEF_ANIMATOR(moveKnockout)
#endif
// seq callbacks
DEF_ANIMATOR(FireballSeqCallback)
DEF_ANIMATOR(Fx33Callback)
@ -240,6 +269,9 @@ DEF_ANIMATOR(PlayerKneelsOver)
DEF_ANIMATOR(FireballTrapSeqCallback)
DEF_ANIMATOR(MGunFireSeqCallback)
DEF_ANIMATOR(MGunOpenSeqCallback)
#ifdef NOONE_EXTENSIONS
DEF_ANIMATOR(weaponShot)
#endif
// event callbacks
@ -269,20 +301,6 @@ DEF_ANIMATOR(callbackMakeMissileBlocking) // 23
DEF_ANIMATOR(fxPodGreenBloodSpray) // 24
#ifdef NOONE_EXTENSIONS
DEF_ANIMATOR(forcePunch)
DEF_ANIMATOR(aiGenDudeMoveForward)
DEF_ANIMATOR(unicultThinkChase)
DEF_ANIMATOR(unicultThinkGoto)
DEF_ANIMATOR(unicultThinkSearch)
DEF_ANIMATOR(genDudeAttack1)
DEF_ANIMATOR(punchCallback)
DEF_ANIMATOR(ThrowCallback1)
DEF_ANIMATOR(ThrowCallback2)
DEF_ANIMATOR(callbackGenDudeUpdate)
#endif
enum EFeatureFlags
{
kFeatureCustomAmmoCount = 1,

View file

@ -23,6 +23,7 @@ public:
double dudeSlope; // Q18.14 format
bool hasx;
bool explosionhackflag; // this originally hijacked the target field which is not safe when working with pointers.
bool chasehackflag; // replaces hackery with non-serializable state data.
XSPRITE xspr;
SPRITEHIT hit;
DUDEEXTRA dudeExtra;
@ -31,12 +32,11 @@ public:
// nnext stuff. For now not exported to scripting.
#ifdef NOONE_EXTENSIONS
SPRITEMASS spriteMass;
GENDUDEEXTRA genDudeExtra;
EventObject condition[4];
TObjPtr<DBloodActor*> prevmarker; // needed by the nnext marker code. This originally hijacked targetX in XSPRITE
#endif
DVector3 basePoint;
int16_t dmgControl[kDamageMax]; // combination of the ones in DUDEINFO, THINGINFO and GENDUDEEXTRA, needs to be modifiable
int16_t dmgControl[kDamageMax]; // combination of the ones in DUDEINFO, THINGINFO, needs to be modifiable
// transient data (not written to savegame)
int cumulDamage;

View file

@ -60,6 +60,30 @@ bool CheckProximity(DBloodActor* actor, const DVector3& pos, sectortype* pSector
return 0;
}
//==========================================================================
//
//
//
//==========================================================================
bool CheckProximityPoint(double nX1, double nY1, double nZ1, double nX2, double nY2, double nZ2, double nDist)
{
double oX = abs(nX2 - nX1);
if (oX >= nDist)
return 0;
double oY = abs(nY2 - nY1);
if (oY >= nDist)
return 0;
if (nZ2 != nZ1)
{
double oZ = abs(nZ2 - nZ1);
if (oZ >= nDist)
return 0;
}
if (oX * oX + oY * oY > nDist * nDist) return 0;
return 1;
}
//---------------------------------------------------------------------------
//
// Note: This function features some very bad math.

View file

@ -33,6 +33,7 @@ enum {
bool CheckProximity(DBloodActor* pSprite, const DVector3& pos, sectortype* pSector, int nDist);
bool CheckProximityPoint(double nX1, double nY1, double nZ1, double nX2, double nY2, double nZ2, double nDist);
int HitScan(DBloodActor* pSprite, double z, const DVector3& pos, unsigned int nMask, double range = 0);
int VectorScan(DBloodActor* pSprite, double nOffset, double nZOffset, const DVector3& vel, double nRange, int ac);

View file

@ -487,6 +487,7 @@ void DBloodActor::Serialize(FSerializer& arc)
("dudeslope", dudeSlope)
("dudeextra", dudeExtra)
("explosionflag", explosionhackflag)
("chasehackflag", chasehackflag)
("spritehit", hit)
("owneractor", ownerActor)
.Array("dmgcontrol", dmgControl, kDamageMax);
@ -498,14 +499,8 @@ void DBloodActor::Serialize(FSerializer& arc)
{
arc//("spritemass", spriteMass) // should always be cached and not written out.
("prevmarker", prevmarker)
.Array("conditions", condition, 2);
.Array("conditions", condition, 4);
// GenDudeExtra only contains valid info for kDudeModernCustom and kDudeModernCustomBurning so only save when needed as these are not small.
if (GetType() == kDudeModernCustom)
{
arc("gendudeextra", genDudeExtra);
}
}
#endif
}

View file

@ -62,11 +62,12 @@ kCdudeFXEffectBase = 0,
kCudeFXEffectCallbackBase = 512,
kCdudeGIBEffectBase = 1024,
kCdudeMinSeeDist = 3000,
kCdudeMinHearDist = (kCdudeMinSeeDist >> 1),
kCdudeBurningHealth = (25 << 4),
};
constexpr double kCdudeMinSeeDist = 3000 * inttoworld;
constexpr double kCdudeMinHearDist = (kCdudeMinSeeDist * 0.5);
class CUSTOMDUDE;
extern VMFunction* nCdudeAppearanceCallback;
extern VMFunction* gCdudeCustomCallback[];
@ -380,13 +381,13 @@ class ARG_PICK_WEAPON
{
public:
DAngle angle;
double distance;
double _distance;
uint8_t dudeHealth;
uint8_t targHealth;
ARG_PICK_WEAPON(DBloodActor* actor, DBloodActor* target)
{
DVector2 distv = target->spr.pos.XY() - actor->spr.pos.XY();
distance = distv.Length();
_distance = distv.Length();
angle = absangle(distv.Angle(), actor->spr.Angles.Yaw);
dudeHealth = CountHealthPerc(actor);
targHealth = CountHealthPerc(target);
@ -394,7 +395,7 @@ class ARG_PICK_WEAPON
ARG_PICK_WEAPON(DBloodActor* actor, DBloodActor* target, double nDist, DAngle nAng)
{
distance = nDist;
_distance = nDist;
angle = nAng;
dudeHealth = CountHealthPerc(actor);
targHealth = CountHealthPerc(target);
@ -647,14 +648,14 @@ class CUSTOMDUDE_WEAPON
CUSTOMDUDE_SOUND sound;
struct SHOT
{
unsigned int velocity;
double _velocity;
signed int slope;
uint16_t targetFollow : 12;
uint16_t clipdist : 8;
uint16_t impact : 2;
int16_t remTime : 14;
DAngle targetFollow;
uint8_t clipdist;
uint8_t impact;
int16_t remTime;
APPEARANCE appearance;
POINT3D offset;
DVector3 offset;
}
shot;
struct AMMO
@ -723,15 +724,16 @@ class CUSTOMDUDE_WEAPON
targHpRange[1] = 255;
shot.remTime = -1;
shot.velocity = INT32_MAX;
shot._velocity = FLT_MAX;
shot.slope = INT32_MAX;
}
char HaveAmmmo(void) { return (!ammo.total || ammo.cur); }
int GetDistance(void) { return ClipLow(distRange[1] - distRange[0], 0); }
int GetDistanceF(void) { return maptoworld * ClipLow(distRange[1] - distRange[0], 0); }
int GetNumshots(void) { return (ammo.total) ? ClipHigh(ammo.cur, numshots) : numshots; }
char IsTimeout(void) { return ((unsigned int)PlayClock < cooldown.clock); }
char HaveSlope(void) { return (shot.slope != INT32_MAX); }
char HaveVelocity(void) { return (shot.velocity != INT32_MAX); }
char HaveVelocity(void) { return (shot._velocity != FLT_MAX); }
};
@ -818,8 +820,8 @@ class CUSTOMDUDE_EFFECT
unsigned short id[kCdudeMaxEffects];
unsigned int clock;
signed int liveTime;
double velocity;
double velocitySlope;
double _velocity;
double _velocitySlope;
DAngle angle;
uint8_t posture;
uint8_t medium;
@ -837,7 +839,7 @@ class CUSTOMDUDE_EFFECT
{
memset(this, 0, sizeof(CUSTOMDUDE_EFFECT));
angle = DAngle360;
velocity = -1;
_velocity = -1;
chance = 0x10000;
srcVelocity = 1;
@ -890,9 +892,9 @@ class CUSTOMDUDE_EFFECT
void Setup(DBloodActor* pSrc, DBloodActor* pEff, bool relVel)
{
DVector3 dvel(0, 0, velocitySlope);
DVector3 dvel(0, 0, _velocitySlope);
DAngle nAng = ((angle != DAngle360) ? (pSrc->spr.Angles.Yaw + angle) : RandomAngle()).Normalized360();
double nVel = velocity;
double nVel = _velocity;
int rp = Random(15);
pEff->ownerActor = pSrc;
@ -1184,7 +1186,7 @@ class CUSTOMDUDE
uint8_t numWeapons;
DUDEEXTRA* pExtra;
DUDEINFO* pInfo;
DBloodActor* pSpr;
DBloodActor* pSpr; // this is our owner so no TObjPtr is needed
TObjPtr<DBloodActor *> pLeech;
CUSTOMDUDE_WEAPON weapons[kCdudeMaxWeapons]; // the weapons it may have
CUSTOMDUDE_WEAPON* pWeapon; // pointer to current weapon
@ -1203,11 +1205,14 @@ class CUSTOMDUDE
unsigned int mass ; // mass in KG
FTextureID largestPic ; // in all states to compare on crouching
sectortype* prevSector ; // the recent sector dude was in
double seeDist ; // dudeInfo duplicate for sleeping
double hearDist ; // dudeInfo duplicate for sleeping
double _seeDist ; // dudeInfo duplicate for sleeping
double _hearDist ; // dudeInfo duplicate for sleeping
DAngle periphery ; // dudeInfo duplicate for sleeping
unsigned int fallHeight ; // in pixels
signed int nextDude ; // -1: none, <-1: vdude, >=0: ins, >=kMaxSprites: cdude
TObjPtr<DBloodActor*> NextDude;
int NextDudeType;
//signed int nextDude ; // -1: none, <-1: vdude, >=0: ins, >=kMaxSprites: cdude
//----------------------------------------------------------------------------------------------------
void PlaySound(int nState) { return (sound[nState].Play(pSpr)); }
int GetStateSeq(int nState, int nPosture) { return states[nState][nPosture].seqId; }
@ -1244,7 +1249,7 @@ class CUSTOMDUDE
char IsTooTight(void);
//----------------------------------------------------------------------------------------------------
CUSTOMDUDE_WEAPON* PickWeapon(ARG_PICK_WEAPON* pArg);
int AdjustSlope(int nTarget, int zOffs);
int AdjustSlope(DBloodActor* nTarget, int zOffs);
char AdjustSlope(int nDist, int* nSlope);
//----------------------------------------------------------------------------------------------------
void InitSprite(void);
@ -1255,7 +1260,7 @@ class CUSTOMDUDE
int Damage(DBloodActor* nFrom, int nDmgType, int nDmg);
void Kill(DBloodActor* nFrom, int nDmgType, int nDmg);
//----------------------------------------------------------------------------------------------------
char CanMove(sectortype* pXSect, char Crusher, char Water, char Uwater, char Depth, int bottom, int floorZ);
char CanMove(sectortype* pXSect, bool Crusher, bool Water, bool Uwater, bool Depth, double bottom, double floorZ);
char FindState(AISTATE* pState, int* nStateType, int* nPosture);
void NewState(int nStateType, int nTimeOverride = -1);
char NewState(AISTATE* pState);

View file

@ -817,7 +817,7 @@ bool nnExtIsImmune(DBloodActor* actor, int dmgType, int minScale)
else if (actor->IsDudeActor())
{
if (actor->IsPlayerActor()) return (getPlayer(actor)->damageControl[dmgType]);
else if (actor->GetType() == kDudeModernCustom) return (cdudeGet(actor)->GetDamage(-1, dmgType) <= minScale);
else if (actor->GetType() == kDudeModernCustom) return (cdudeGet(actor)->GetDamage(nullptr, dmgType) <= minScale);
return (actor->dmgControl[dmgType] <= minScale);
}
}
@ -1667,8 +1667,6 @@ int getSpriteMassBySize(DBloodActor* actor)
switch (actor->GetType())
{
case kDudeModernCustom:
seqId = actor->xspr.data2;
clipDist = actor->genDudeExtra.clipdist;
break;
default:
seqId = getDudeInfo(actor)->seqStartID;
@ -2643,19 +2641,6 @@ void useObjResizer(DBloodActor* sourceactor, int targType, sectortype* targSect,
}
}
#if 0
if (fit && (targetactor->GetType() == kDudeModernCustom)
{
// request properties update for custom dude
targetactor->genDudeExtra.updReq[kGenDudePropertySpriteSize] = true;
targetactor->genDudeExtra.updReq[kGenDudePropertyAttack] = true;
targetactor->genDudeExtra.updReq[kGenDudePropertyMass] = true;
targetactor->genDudeExtra.updReq[kGenDudePropertyDmgScale] = true;
evPostActor(targetactor, kGenDudeUpdTimeRate, AF(callbackGenDudeUpdate));
}
#endif
if (valueIsBetween(sourceactor->xspr.data3, -1, 32767))
targetactor->spr.xoffset = ClipRange(sourceactor->xspr.data3, 0, 255);
@ -8747,7 +8732,7 @@ char nnExtOffsetSprite(DBloodActor* pSpr, const DVector3& opos)
//
//---------------------------------------------------------------------------
void nnExtScaleVelocity(DBloodActor* pSpr, int nVel, const DVector3& vel, int which)
void nnExtScaleVelocity(DBloodActor* pSpr, double nVel, const DVector3& vel, int which)
{
if (which & 0x01)
{
@ -8767,7 +8752,7 @@ void nnExtScaleVelocity(DBloodActor* pSpr, int nVel, const DVector3& vel, int wh
//
//---------------------------------------------------------------------------
void nnExtScaleVelocityRel(DBloodActor* pSpr, int nVel, const DVector3& vel, int which)
void nnExtScaleVelocityRel(DBloodActor* pSpr, double nVel, const DVector3& vel, int which)
{
if (which & 0x01)
{
@ -8919,34 +8904,6 @@ int nnExtDudeStartHealth(DBloodActor* pSpr, int nHealth)
return getDudeInfo(pSpr->GetType())->startHealth << 4;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
FSerializer& Serialize(FSerializer& arc, const char* keyname, GENDUDEEXTRA& w, GENDUDEEXTRA* def)
{
if (arc.BeginObject(keyname))
{
arc ("clipdist", w.clipdist)
.Array("availdeaths", w.availDeaths, kDamageMax)
("movespeed", w.moveSpeed)
("firedist", w.fireDist)
("throwdist", w.throwDist)
("curweapon", w.curWeapon)
("weapontype", w.weaponType)
("basedispersion", w.baseDispersion)
("slavecount", w.slaveCount)
("lifeleech", w.pLifeLeech)
.Array("slaves", w.slave, w.slaveCount)
.Array("updreq", w.updReq, kGenDudePropertyMax)
("flags", w.flags)
.EndObject();
}
return arc;
}
#if 0 // no need to save if we ensure it never gets accessed directly without validating the content
FSerializer& Serialize(FSerializer& arc, const char* keyname, SPRITEMASS& w, SPRITEMASS* def)
{
@ -8967,6 +8924,8 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, SPRITEMASS& w, SPR
}
#endif
void SerializeConditions(FSerializer& arc);
void SerializeNNExts(FSerializer& arc)
{
if (arc.BeginObject("nnexts"))
@ -8979,6 +8938,7 @@ void SerializeNNExts(FSerializer& arc)
("eventredirects", gEventRedirectsUsed);
gSprNSect.Serialize(arc);
SerializeConditions(arc);
arc.EndObject();
}
}

View file

@ -1849,6 +1849,13 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, TRACKING_CONDITION
return arc;
}
void SerializeConditions(FSerializer& arc)
{
// if this gets run before loading a map it needs to run the one-time init code before deserializing the data.
if (arc.isReading() && gConditions.Size() == 0) conditionInitData();
arc("conditions", gTrackingConditionsList);
}
static void TriggerObject(EventObject nSerial, DBloodActor* pCond)
{