- migrated attackertype to class objects.

This commit is contained in:
Christoph Oelckers 2022-12-16 16:56:47 +01:00
parent ae4ef6401c
commit da0b429751
22 changed files with 109 additions and 128 deletions

View file

@ -308,6 +308,13 @@ inline FSerializer& Serialize(FSerializer& arc, const char* key, BitArray& value
}
template<> FSerializer& Serialize(FSerializer& arc, const char* key, PClass*& clst, PClass** def);
template<> inline FSerializer& Serialize(FSerializer& arc, const char* key, PClassActor*& clst, PClassActor** def)
{
PClass* c = (PClass*)clst;
Serialize(arc, key, c, (PClass**)def);
clst = (PClassActor*)c;
return arc;
}
template<> FSerializer& Serialize(FSerializer& arc, const char* key, FFont*& font, FFont** def);
template<> FSerializer &Serialize(FSerializer &arc, const char *key, Dictionary *&dict, Dictionary **def);

View file

@ -585,7 +585,7 @@ void movefallers(void)
int j = fi.ifhitbyweapon(act);
if (j >= 0)
{
if (gs.actorinfo[j].flags2 & SFLAG2_EXPLOSIVE)
if (j == 2) // explosive
{
if (act->spr.extra <= 0)
{
@ -3358,7 +3358,7 @@ void fall_common(DDukeActor *actor, int playernum, int JIBS6, int DRONE, int BLO
SKIPJIBS:
actor->attackertype = SHOTSPARK1;
actor->attackertype = PClass::FindActor(NAME_DukeShotSpark);
actor->hitextra = 1;
actor->vel.Z = 0;
}

View file

@ -131,7 +131,7 @@ bool ifsquished(DDukeActor* actor, int p)
if (actor->spr.pal == 1)
{
actor->attackertype = DTILE_SHOTSPARK1;
actor->attackertype = PClass::FindActor(NAME_DukeShotSpark);
actor->hitextra = 1;
return false;
}
@ -239,29 +239,8 @@ void hitradius_d(DDukeActor* actor, int r, int hp1, int hp2, int hp3, int h
if (dist < radius && cansee(act2->spr.pos.plusZ(-8), act2->sector(), actor->spr.pos.plusZ(-12), actor->sector()))
{
act2->hitang = (act2->spr.pos - actor->spr.pos).Angle();
act2->attackertype = CallGetRadiusDamageType(actor, act2->spr.extra);
if (actor->spr.picnum == DTILE_RPG && act2->spr.extra > 0)
act2->attackertype = DTILE_RPG;
else if (!isWorldTour())
{
if (actor->spr.picnum == DTILE_SHRINKSPARK)
act2->attackertype = DTILE_SHRINKSPARK;
else act2->attackertype = DTILE_RADIUSEXPLOSION;
}
else
{
if (actor->spr.picnum == DTILE_SHRINKSPARK || actor->spr.picnum == DTILE_FLAMETHROWERFLAME)
act2-> attackertype = actor->spr.picnum;
else if (actor->spr.picnum != DTILE_FIREBALL || !Owner || !Owner->isPlayer())
{
if (actor->spr.picnum == DTILE_LAVAPOOL)
act2->attackertype = DTILE_FLAMETHROWERFLAME;
else
act2->attackertype = DTILE_RADIUSEXPLOSION;
}
else
act2->attackertype = DTILE_FLAMETHROWERFLAME;
}
if (actor->spr.picnum != DTILE_SHRINKSPARK && (!isWorldTour() || actor->spr.picnum != DTILE_LAVAPOOL))
{
@ -298,7 +277,7 @@ void hitradius_d(DDukeActor* actor, int r, int hp1, int hp2, int hp3, int h
{
int p = act2->spr.yint;
if (isWorldTour() && act2->attackertype == DTILE_FLAMETHROWERFLAME && Owner->isPlayer())
if (act2->attackertype->TypeName == NAME_DukeFlamethrowerFlame && Owner->isPlayer())
{
ps[p].numloogs = -1 - actor->spr.yint;
}
@ -433,11 +412,12 @@ int ifhitbyweapon_d(DDukeActor *actor)
if (actor->hitextra >= 0)
{
auto adef = actor->attackerDefaults();
if (actor->spr.extra >= 0)
{
if (actor->isPlayer())
{
if (ud.god && actor->attackertype != DTILE_SHRINKSPARK) return -1;
if (ud.god && !(adef->flags3 & SFLAG3_LIGHTDAMAGE)) return -1;
p = actor->PlayerIndex();
@ -451,7 +431,7 @@ int ifhitbyweapon_d(DDukeActor *actor)
if (hitowner)
{
if (actor->spr.extra <= 0 && actor->attackertype != DTILE_FREEZEBLAST)
if (actor->spr.extra <= 0 && !(adef->flags2 & SFLAG2_FREEZEDAMAGE))
{
actor->spr.extra = 0;
@ -465,7 +445,7 @@ int ifhitbyweapon_d(DDukeActor *actor)
}
}
if (attackerflag(actor, SFLAG2_DOUBLEDMGTHRUST))
if (adef->flags2 & SFLAG2_DOUBLEDMGTHRUST)
{
ps[p].vel.XY() += actor->hitang.ToVector() * actor->hitextra * 0.25;
}
@ -477,13 +457,12 @@ int ifhitbyweapon_d(DDukeActor *actor)
else
{
if (actor->hitextra == 0)
if (actor->attackertype == DTILE_SHRINKSPARK && actor->spr.scale.X < 0.375)
if (actor->attackertype->TypeName == NAME_DukeShrinkSpark && actor->spr.scale.X < 0.375)
return -1;
if (isWorldTour() && actor->attackertype == DTILE_FIREFLY && actor->spr.scale.X < 0.75)
if (actor->attackertype->TypeName == NAME_DukeFirefly && actor->spr.scale.X < 0.75)
{
if (actor->attackertype != DTILE_RADIUSEXPLOSION && actor->attackertype != DTILE_RPG)
return -1;
return -1;
}
actor->spr.extra -= actor->hitextra;
@ -493,13 +472,18 @@ int ifhitbyweapon_d(DDukeActor *actor)
}
actor->hitextra = -1;
return actor->attackertype;
// makeshift damage type reporting. Needs improvement and generalization later.
int res = 0;
if (adef->flags2 & SFLAG2_FREEZEDAMAGE) res |= 1;
if (adef->flags2 & SFLAG2_EXPLOSIVE) res |= 2;
return res;
}
}
if (ud.multimode < 2 || !isWorldTour()
|| actor->attackertype != DTILE_FLAMETHROWERFLAME
if (ud.multimode < 2
|| actor->attackertype == nullptr
|| actor->attackertype->TypeName != NAME_DukeFlamethrowerFlame
|| actor->hitextra >= 0
|| actor->spr.extra > 0
|| !actor->isPlayer()
@ -521,7 +505,7 @@ int ifhitbyweapon_d(DDukeActor *actor)
actor->SetHitOwner(ps[p].GetActor());
actor->hitextra = -1;
return DTILE_FLAMETHROWERFLAME;
return 0;
}
}

View file

@ -231,13 +231,7 @@ void hitradius_r(DDukeActor* actor, int r, int hp1, int hp2, int hp3, int h
}
act2->hitang = (act2->spr.pos - actor->spr.pos).Angle();
if (actor->spr.picnum == RTILE_RPG && act2->spr.extra > 0)
act2->attackertype = RTILE_RPG;
else if ((isRRRA()) && actor->spr.picnum == RTILE_RPG2 && act2->spr.extra > 0)
act2->attackertype = RTILE_RPG;
else
act2->attackertype = RTILE_RADIUSEXPLOSION;
act2->attackertype = CallGetRadiusDamageType(actor, act2->spr.extra);
if (dist < radius / 3)
{
@ -374,6 +368,7 @@ int ifhitbyweapon_r(DDukeActor *actor)
if (actor->hitextra >= 0)
{
auto adef = actor->attackerDefaults();
if (actor->spr.extra >= 0)
{
if (actor->isPlayer())
@ -392,7 +387,7 @@ int ifhitbyweapon_r(DDukeActor *actor)
if (hitowner)
{
if (actor->spr.extra <= 0 && actor->attackertype != RTILE_FREEZEBLAST)
if (actor->spr.extra <= 0 && !(adef->flags2 & SFLAG2_FREEZEDAMAGE))
{
actor->spr.extra = 0;
@ -406,7 +401,7 @@ int ifhitbyweapon_r(DDukeActor *actor)
}
}
if (attackerflag(actor, SFLAG2_DOUBLEDMGTHRUST))
if (adef->flags2 & SFLAG2_DOUBLEDMGTHRUST)
{
ps[p].vel.XY() += actor->hitang.ToVector() * actor->hitextra * 0.25;
}
@ -428,7 +423,11 @@ int ifhitbyweapon_r(DDukeActor *actor)
}
actor->hitextra = -1;
return actor->attackertype;
// makeshift damage type reporting. Needs improvement and generalization later.
int res = 0;
if (adef->flags2 & SFLAG2_FREEZEDAMAGE) res |= 1;
if (adef->flags2 & SFLAG2_EXPLOSIVE) res |= 2;
return res;
}
}
@ -1570,7 +1569,7 @@ static int fallspecial(DDukeActor *actor, int playernum)
addspritetodelete();
return 0;
}
actor->attackertype = RTILE_SHOTSPARK1;
actor->attackertype = PClass::FindActor(NAME_DukeShotSpark);
actor->hitextra = 1;
}
else if (tilesurface(actor->sector()->floortexture) == TSURF_MAGMA)
@ -1579,7 +1578,7 @@ static int fallspecial(DDukeActor *actor, int playernum)
{
if ((krand() & 3) == 1)
{
actor->attackertype = RTILE_SHOTSPARK1;
actor->attackertype = PClass::FindActor(NAME_DukeShotSpark);
actor->hitextra = 5;
}
}
@ -1631,7 +1630,7 @@ void destroyit(DDukeActor *actor)
{
if (a3->spr.picnum == RTILE_DESTRUCTO)
{
a3->attackertype = RTILE_SHOTSPARK1;
a3->attackertype = PClass::FindActor(NAME_DukeShotSpark);
a3->hitextra = 1;
}
}

View file

@ -124,6 +124,9 @@ void CallPlayFTASound(DDukeActor* actor);
void CallStandingOn(DDukeActor* actor, player_struct* p);
void CallRunState(DDukeActor* actor);
int CallTriggerSwitch(DDukeActor* actor, player_struct* p);
PClassActor* CallGetRadiusDamageType(DDukeActor* actor, int targhealth);
extern FTextureID mirrortex, foftex;

View file

@ -255,7 +255,6 @@ void initactorflags_d()
setflag(SFLAG3_BLOODY, { DTILE_BLOODPOOL });
// The feature guarded by this flag does not exist in Duke, it always acts as if the flag was set.
for (auto& ainf : gs.actorinfo) ainf.flags |= SFLAG_LOOKALLAROUND;
gs.actorinfo[DTILE_ORGANTIC].aimoffset = 32;
gs.actorinfo[DTILE_ROTATEGUN].aimoffset = 32;

View file

@ -95,8 +95,8 @@ void initactorflags_r()
setflag(SFLAG_INTERNAL_BADGUY, { RTILE_PIG, RTILE_HEN });
gs.actorinfo[RTILE_DRONE].flags |= SFLAG_NOWATERDIP;
gs.actorinfo[RTILE_VIXEN].flags |= SFLAG_LOOKALLAROUND;
//gs.actorinfo[RTILE_DRONE].flags |= SFLAG_NOWATERDIP;
//gs.actorinfo[RTILE_VIXEN].flags |= SFLAG_LOOKALLAROUND;
if (isRRRA())
{
setflag(SFLAG_LOOKALLAROUND, { RTILE_COOT, RTILE_COOTSTAYPUT, RTILE_BIKERB, RTILE_BIKERBV2, RTILE_CHEER, RTILE_CHEERB,
@ -197,7 +197,7 @@ void initactorflags_r()
// Animals were not supposed to have this, but due to a coding bug the logic was unconditional for everything in the game.
for (auto& ainf : gs.actorinfo)
{
ainf.flags |= SFLAG_MOVEFTA_WAKEUPCHECK;
//ainf.flags |= SFLAG_MOVEFTA_WAKEUPCHECK;
}
@ -221,11 +221,11 @@ void initactorflags_r()
setflag(SFLAG2_FLOATING, { RTILE_UFO1_RR, RTILE_UFO2, RTILE_UFO3, RTILE_UFO4, RTILE_UFO5 });
}
gs.actorinfo[RTILE_RPG2].flags |= SFLAG_FORCEAUTOAIM;
//gs.actorinfo[RTILE_RPG2].flags |= SFLAG_FORCEAUTOAIM;
// clear some bad killcount defaults
for (auto t : { RTILE_COW, RTILE_HEN, RTILE_PIG, RTILE_MINECARTKILLER, RTILE_UFOBEAM }) gs.actorinfo[t].flags &= ~SFLAG_KILLCOUNT;
if (isRRRA()) gs.actorinfo[RTILE_WACOWINDER].flags &= ~SFLAG_KILLCOUNT;
//for (auto t : { RTILE_COW, RTILE_HEN, RTILE_PIG, RTILE_MINECARTKILLER, RTILE_UFOBEAM }) gs.actorinfo[t].flags &= ~SFLAG_KILLCOUNT;
//if (isRRRA()) gs.actorinfo[RTILE_WACOWINDER].flags &= ~SFLAG_KILLCOUNT;
gs.weaponsandammosprites[0] = RTILE_CROSSBOWSPRITE;
gs.weaponsandammosprites[1] = RTILE_RIFLEGUNSPRITE;

View file

@ -571,6 +571,19 @@ int CallTriggerSwitch(DDukeActor* actor, player_struct* p)
return nval;
}
PClassActor* CallGetRadiusDamageType(DDukeActor* actor, int targhealth)
{
PClassActor* nval = nullptr;
IFVIRTUALPTR(actor, DDukeActor, GetRadiusDamageType)
{
VMReturn ret;
ret.PointerAt((void**)&nval);
VMValue val[] = { actor, targhealth };
VMCall(func, val, 2, &ret, 1);
}
return nval;
}
CCMD(changewalltexture)
{

View file

@ -1204,10 +1204,10 @@ int ConCompiler::parsecommand()
if (tw == concmd_useractor)
{
if (j & 1)
gs.actorinfo[lnum].flags |= SFLAG_BADGUY | SFLAG_KILLCOUNT;
gs.actorinfo[lnum].enemyflags |= SFLAG_BADGUY | SFLAG_KILLCOUNT;
if (j & 2)
gs.actorinfo[lnum].flags |= (SFLAG_BADGUY | SFLAG_KILLCOUNT | SFLAG_BADGUYSTAYPUT);
gs.actorinfo[lnum].enemyflags |= (SFLAG_BADGUY | SFLAG_KILLCOUNT | SFLAG_BADGUYSTAYPUT);
}
for (j = 0; j < 4; j++)

View file

@ -1245,10 +1245,6 @@ void DoActor(bool bSet, int lVar1, int lLabelID, int lVar2, DDukeActor* sActor,
if (bSet) act->cgg = lValue;
else SetGameVarID(lVar2, act->cgg, sActor, sPlayer);
break;
case ACTOR_HTPICNUM:
if (bSet) act->attackertype = lValue;
else SetGameVarID(lVar2, act->attackertype, sActor, sPlayer);
break;
case ACTOR_HTANG:
if (bSet) act->hitang = mapangle(lValue);
else SetGameVarID(lVar2, act->hitang.Buildang(), sActor, sPlayer);
@ -1908,7 +1904,7 @@ int ParseState::parse(void)
case concmd_ifwasweapon:
case concmd_ifspawnedby: // these two are the same
insptr++;
parseifelse( g_ac->attackertype == *insptr);
parseifelse( g_ac->attackertype == GetSpawnType(*insptr));
break;
case concmd_ifai:
insptr++;
@ -2079,12 +2075,8 @@ int ParseState::parse(void)
case concmd_guts:
{
insptr += 2;
auto info = spawnMap.CheckKey(*(insptr - 1));
if (info)
{
auto clstype = info->cls;
if (clstype) spawnguts(g_ac, clstype, *insptr);
}
auto clstype = GetSpawnType(*(insptr - 1));
if (clstype) spawnguts(g_ac, clstype, *insptr);
insptr++;
break;
}

View file

@ -52,26 +52,6 @@ inline int iseffector(DDukeActor* actor)
}
inline int badguypic(int const tileNum)
{
return ((gs.actorinfo[tileNum].flags & (SFLAG_INTERNAL_BADGUY | SFLAG_BADGUY)) != 0);
}
inline int bossguypic(int const tileNum)
{
return ((gs.actorinfo[tileNum].flags & (SFLAG_BOSS)) != 0);
}
inline int attackerflag(DDukeActor* actor, EDukeFlags1 mask)
{
return (((gs.actorinfo[actor->attackertype].flags) & mask) != 0);
}
inline int attackerflag(DDukeActor* actor, EDukeFlags2 mask)
{
return (((gs.actorinfo[actor->attackertype].flags2) & mask) != 0);
}
inline void setflag(EDukeFlags1 flag, const std::initializer_list<short>& types)
{
for (auto val : types)

View file

@ -2281,7 +2281,7 @@ void onMotorcycleHit(int snum, DDukeActor* victim)
}
else
victim->SetHitOwner(p->GetActor());
victim->attackertype = RTILE_MOTOHIT;
victim->attackertype = PClass::FindActor(NAME_RedneckMotoHit);
victim->hitextra = int(p->MotoSpeed * 0.5);
p->MotoSpeed -= p->MotoSpeed / 4.;
p->TurbCount = 6;
@ -2315,7 +2315,7 @@ void onBoatHit(int snum, DDukeActor* victim)
}
else
victim->SetHitOwner(p->GetActor());
victim->attackertype = RTILE_MOTOHIT;
victim->attackertype = PClass::FindActor(NAME_RedneckMotoHit);
victim->hitextra = int(p->MotoSpeed * 0.25);
p->MotoSpeed -= p->MotoSpeed / 4.;
p->TurbCount = 6;
@ -3201,7 +3201,7 @@ void processinput_r(int snum)
{
if (badguy(clz.actor()))
{
clz.actor()->attackertype = RTILE_MOTOHIT;
clz.actor()->attackertype = PClass::FindActor(NAME_RedneckMotoHit);
clz.actor()->hitextra = int(2 + (p->MotoSpeed * 0.5));
p->MotoSpeed -= p->MotoSpeed * (1. / 16.);
}

View file

@ -225,7 +225,7 @@ void checkhitdefault_d(DDukeActor* targ, DDukeActor* proj)
if ((proj->flags2 & SFLAG2_FREEZEDAMAGE) && ((targ->isPlayer() && targ->spr.pal == 1) || (gs.freezerhurtowner == 0 && proj->GetOwner() == targ)))
return;
int hitpic = proj->spr.picnum;
auto hitpic = static_cast<PClassActor*>(proj->GetClass());
auto Owner = proj->GetOwner();
if (Owner && Owner->isPlayer())
{
@ -233,8 +233,8 @@ void checkhitdefault_d(DDukeActor* targ, DDukeActor* proj)
return;
auto tOwner = targ->GetOwner();
if (isWorldTour() && hitpic == DTILE_FIREBALL && tOwner && tOwner->spr.picnum != DTILE_FIREBALL)
hitpic = DTILE_FLAMETHROWERFLAME;
if (hitpic->TypeName == NAME_DukeFireball && tOwner && tOwner->GetClass()->TypeName != NAME_DukeFireball)
hitpic = PClass::FindActor(NAME_DukeFlamethrowerFlame);
}
targ->attackertype = hitpic;

View file

@ -210,7 +210,7 @@ void checkhitdefault_r(DDukeActor* targ, DDukeActor* proj)
if (proj->spr.picnum == RTILE_FREEZEBLAST && ((targ->isPlayer() && targ->spr.pal == 1) || (gs.freezerhurtowner == 0 && proj->GetOwner() == targ)))
return;
targ->attackertype = proj->spr.picnum;
targ->attackertype = static_cast<PClassActor*>(proj->GetClass());
targ->hitextra += proj->spr.extra;
if (targ->spr.picnum != RTILE_COW)
targ->hitang = proj->spr.Angles.Yaw;
@ -646,7 +646,7 @@ void tearitup(sectortype* sect)
{
if (act->spr.picnum == RTILE_DESTRUCTO)
{
act->attackertype = RTILE_SHOTSPARK1;
act->attackertype = PClass::FindActor(NAME_DukeShotSpark);
act->hitextra = 1;
}
}

View file

@ -107,7 +107,7 @@ DDukeActor* CreateActor(sectortype* whatsectp, const DVector3& pos, PClassActor*
if (s_ow)
{
act->attackertype = s_ow->spr.picnum;
act->attackertype = static_cast<PClassActor*>(s_ow->GetClass());
act->floorz = s_ow->floorz;
act->ceilingz = s_ow->ceilingz;
}
@ -168,7 +168,7 @@ DDukeActor* SpawnActor(sectortype* whatsectp, const DVector3& pos, PClassActor*
bool initspriteforspawn(DDukeActor* act)
{
SetupGameVarsForActor(act);
act->attackertype = act->spr.picnum;
act->attackertype = static_cast<PClassActor*>(act->GetClass());
act->timetosleep = 0;
act->hitextra = -1;
@ -268,7 +268,7 @@ DDukeActor* spawn(DDukeActor* actj, int pn)
auto spawned = CreateActor(actj->sector(), actj->spr.pos, pn, 0, DVector2(0, 0), nullAngle, 0., 0., actj, 0);
if (spawned)
{
spawned->attackertype = actj->spr.picnum;
spawned->attackertype = static_cast<PClassActor*>(actj->GetClass());
return spawninit(actj, spawned, nullptr);
}
}
@ -282,7 +282,7 @@ DDukeActor* spawn(DDukeActor* actj, PClassActor * cls)
auto spawned = CreateActor(actj->sector(), actj->spr.pos, cls, 0, DVector2(0, 0), nullAngle, 0., 0., actj, 0);
if (spawned)
{
spawned->attackertype = actj->spr.picnum;
spawned->attackertype = static_cast<PClassActor*>(actj->GetClass());
return spawninit(actj, spawned, nullptr);
}
}
@ -322,6 +322,7 @@ bool commonEnemySetup(DDukeActor* self, DDukeActor* owner)
addtokills(self);
self->flags1 &= ~SFLAG_KILLCOUNT;
self->timetosleep = 0;
if (!self->mapSpawned)
{

View file

@ -25,9 +25,7 @@ struct STATUSBARTYPE
struct ActorInfo
{
uint32_t scriptaddress;
EDukeFlags1 flags;
EDukeFlags2 flags2;
EDukeFlags3 flags3;
EDukeFlags1 enemyflags; // placeholder during parsing. Since CON gets parsed before the spawn type table we cannot copy these to their final location yet.
int aimoffset;
int falladjustz;
int gutsoffset;
@ -39,11 +37,17 @@ class DDukeActor : public DCoreActor
HAS_OBJECT_POINTERS
public:
TObjPtr<DDukeActor*> ownerActor, hitOwnerActor;
PClassActor* attackertype;
const DDukeActor* attackerDefaults()
{
return static_cast<DDukeActor*>(GetDefaultByType(attackertype? attackertype : RUNTIME_CLASS(DDukeActor)));
}
uint8_t cgg;
uint8_t spriteextra; // moved here for easier maintenance. This was originally a hacked in field in the sprite structure called 'filler'.
uint16_t movflag;
short attackertype, hitextra;
short hitextra;
short tempval, basepicnum;
unsigned short timetosleep;
bool mapSpawned;

View file

@ -212,6 +212,7 @@ DEFINE_GLOBAL(camsprite)
//---------------------------------------------------------------------------
DEFINE_FIELD(DDukeActor, ownerActor)
DEFINE_FIELD(DDukeActor, attackertype)
DEFINE_FIELD(DDukeActor, hitOwnerActor)
DEFINE_FIELD(DDukeActor, cgg)
DEFINE_FIELD(DDukeActor, spriteextra)
@ -726,21 +727,6 @@ DEFINE_ACTION_FUNCTION(DDukeActor, actorflag3)
ACTION_RETURN_BOOL(!!(self->flags3 & EDukeFlags3::FromInt(mask)));
}
DEFINE_ACTION_FUNCTION(DDukeActor, attackerflag1)
{
PARAM_SELF_PROLOGUE(DDukeActor);
PARAM_INT(mask);
ACTION_RETURN_BOOL(!!attackerflag(self, EDukeFlags1::FromInt(mask)));
}
DEFINE_ACTION_FUNCTION(DDukeActor, attackerflag2)
{
PARAM_SELF_PROLOGUE(DDukeActor);
PARAM_INT(mask);
ACTION_RETURN_BOOL(!!attackerflag(self, EDukeFlags2::FromInt(mask)));
}
//---------------------------------------------------------------------------
//
// DukePlayer

View file

@ -192,4 +192,5 @@ spawnclasses
78 = RedneckMotoAmmo
8460 = RedneckBoatAmmo
7170 = RedneckMotoHit
}

View file

@ -69,6 +69,15 @@ class DukeShotSpark : DukeActor
}
}
class RedneckMotoHit : DukeActor
{
default
{
pic "MOTOHIT";
}
}
// placeholders for CON scripted actors where we need the class.
class DukeForceRipple : DukeActor

View file

@ -32,7 +32,7 @@ class DukeCrack : DukeActor
{
self.temp_data[0] = self.cstat;
self.temp_angle = self.angle;
if (self.ifhitbyweapon() >= 0 && self.attackerflag2(SFLAG2_EXPLOSIVE))
if (self.ifhitbyweapon() == 2) // explosive damage
{
DukeStatIterator it;
for(let a1 = it.First(STAT_STANDABLE); a1; a1 = it.Next())

View file

@ -70,7 +70,7 @@ class DukeGreenSlime : DukeActor
j = self.ifhitbyweapon();
if (j >= 0)
{
if (self.attackerflag2(SFLAG2_FREEZEDAMAGE))
if (j == 1) // freeze damage
return;
for (j = 16; j >= 0; j--)
{
@ -216,7 +216,7 @@ class DukeGreenSlime : DukeActor
if (p.somethingonplayer == self)
p.somethingonplayer = nullptr;
if (self.attackerflag2(SFLAG2_FREEZEDAMAGE))
if (j == 1) // freeze damage
{
self.PlayActorSound("SOMETHINGFROZE");
self.temp_data[0] = -5; self.temp_data[3] = 0;

View file

@ -145,14 +145,15 @@ class DukeActor : CoreActor native
native void SetSpritesetImage(int index);
native int GetSpritesetSize();
native class<DukeActor> attackertype;
native DukeActor ownerActor, hitOwnerActor;
native uint8 cgg;
native uint8 spriteextra; // moved here for easier maintenance. This was originally a hacked in field in the sprite structure called 'filler'.
native int16 /*attackertype, hitang,*/ hitextra, movflag;
native int16 hitextra, movflag;
native int16 tempval; /*, dispicnum;*/
native int16 timetosleep;
native bool mapSpawned;
native double floorz, ceilingz;
native double floorz, ceilingz, hitang;
native int saved_ammo;
native int palvals;
native int temp_data[6];
@ -207,6 +208,10 @@ class DukeActor : CoreActor native
{
return false;
}
virtual class<DukeActor> GetRadiusDamageType(int targhealth)
{
return 'DukeRadiusExplosion';
}
native void RandomScrap();
native void hitradius(int r, int hp1, int hp2, int hp3, int hp4);
@ -231,8 +236,6 @@ class DukeActor : CoreActor native
native int actorflag1(int mask);
native int actorflag2(int mask);
native int actorflag3(int mask);
native int attackerflag1(int mask);
native int attackerflag2(int mask);