- RR cactus stuff

This commit is contained in:
Christoph Oelckers 2022-11-22 17:53:46 +01:00
parent c48dfc082f
commit 1ac4aee0c1
16 changed files with 291 additions and 156 deletions

View file

@ -258,14 +258,6 @@ void FActorInfo::ResolveTextures(const char* clsname, DCoreActor* defaults)
if (defaults->spritesetindex < 0 || defaults->spritesetindex >= (int)SpriteSet.Size()) defaults->spritesetindex = 0;
defaults->spr.picnum = SpriteSet[defaults->spritesetindex]; // Unless picnum is specified it will be set to the given image of the sprite set.
}
if (PicName.IsNotEmpty())
{
defaults->spr.picnum = TileFiles.tileForName(PicName);
#ifdef _DEBUG
if (defaults->spr.picnum == -1) Printf(TEXTCOLOR_RED "Unknown texture '%s' in pic for class %s\n", PicName.GetChars(), clsname);
#endif
}
SpriteSetNames.Reset();
PicName = "";
}

View file

@ -47,7 +47,6 @@ struct FActorInfo
int Health = 0; // not used yet - this will stand in if no CON defines a health value for Duke.
// these are temporary. Due to how Build games handle their tiles, we cannot look up the textures when scripts are being parsed.
FString PicName;
TArray<FString> SpriteSetNames;
FActorInfo() = default;
@ -57,7 +56,6 @@ struct FActorInfo
TypeNum = other.TypeNum;
DefaultFlags = other.DefaultFlags;
DefaultCstat = other.DefaultCstat;
PicName = other.PicName;
SpriteSetNames = other.SpriteSetNames;
}

View file

@ -305,15 +305,13 @@ static bool PointerCheck(PType *symtype, PType *checktype)
//==========================================================================
//
// Default spritetype fields cannot be set directly
// they need to be combined with the data from the map, so they need to be
// stored outside the actual actor until the spawn code can init it.
//
//==========================================================================
DEFINE_PROPERTY(pic, S, CoreActor)
{
PROP_STRING_PARM(str, 0);
bag.Info->ActorInfo()->PicName = str;
info->ActorInfo()->SpriteSetNames.Clear();
info->ActorInfo()->SpriteSetNames.Push(str);
bag.Info->ActorInfo()->DefaultFlags |= DEFF_PICNUM;
}

View file

@ -2581,8 +2581,6 @@ void moveexplosions_r(void) // STATNUM 5
break;
case RRTILE2460:
case RRTILE2465:
case BIKEJIBA:
case BIKEJIBB:
case BIKEJIBC:
@ -2624,8 +2622,7 @@ void moveexplosions_r(void) // STATNUM 5
case DUKETORSO:
case DUKEGUN:
case DUKELEG:
if (!jibs(act, JIBS6, false, true, true, act->spr.picnum == DUKELEG || act->spr.picnum == DUKETORSO || act->spr.picnum == DUKEGUN,
isRRRA() && (act->spr.picnum == RRTILE2465 || act->spr.picnum == RRTILE2560))) continue;
if (!jibs(act, JIBS6, false, true, true, act->spr.picnum == DUKELEG || act->spr.picnum == DUKETORSO || act->spr.picnum == DUKEGUN, false)) continue;
if (act->sector()->lotag == 800)
if (act->spr.pos.Z >= act->sector()->floorz - 8)

View file

@ -526,8 +526,6 @@ void animatesprites_r(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi
break;
case RRTILE2460:
case RRTILE2465:
case BIKEJIBA:
case BIKEJIBB:
case BIKEJIBC:

View file

@ -123,6 +123,7 @@ void CallOnHit(DDukeActor* actor, DDukeActor* hitter);
void CallOnHurt(DDukeActor* actor, player_struct* hitter);
void CallOnTouch(DDukeActor* actor, player_struct* hitter);
bool CallOnUse(DDukeActor* actor, player_struct* user);
void CallOnMotoSmash(DDukeActor* actor, player_struct* hitter);
void CallOnRespawn(DDukeActor* actor, int low);
bool CallAnimate(DDukeActor* actor, tspritetype* hitter);
void CallStaticSetup(DDukeActor* actor);

View file

@ -466,6 +466,16 @@ bool CallOnUse(DDukeActor* actor, player_struct* user)
return nval;
}
void CallOnMotoSmash(DDukeActor* actor, player_struct* hitter)
{
IFVIRTUALPTR(actor, DDukeActor, onMotoSmash)
{
VMValue val[2] = { actor, hitter };
VMCall(func, val, 2, nullptr, 0);
}
}
void CallOnRespawn(DDukeActor* actor, int low)
{
IFVIRTUALPTR(actor, DDukeActor, onRespawn)

View file

@ -689,18 +689,18 @@ y(RRTILE2326, 2326)
y(RRTILE2329, 2329)
y(RRTILE2357, 2357)
y(RRTILE2382, 2382)
y(RRTILE2430, 2430)
y(RRTILE2431, 2431)
y(RRTILE2432, 2432)
x(CACTUSLARGEYELLOW, 2430)
x(CACTUSLARGEGREEN, 2431)
x(CACTUSLARGEBROWN, 2432)
y(RRTILE2437, 2437)
y(RRTILE2443, 2443)
x(CACTUSDRUG, 2443)
y(RRTILE2445, 2445)
y(RRTILE2446, 2446)
x(CACTUSLARGEGREEN2, 2446)
y(RRTILE2450, 2450)
y(RRTILE2451, 2451)
y(RRTILE2455, 2455)
y(RRTILE2460, 2460)
y(RRTILE2465, 2465)
x(CACTUSWITHHOLES, 2451)
x(CACTUSSMALL, 2455)
x(CACTUSDEBRIS1, 2460)
x(CACTUSDEBRIS2, 2465)
x(BONUSSCREEN, 2510)
x(VIEWBORDER, 2520)
x(VICTORY1, 2530)

View file

@ -2445,33 +2445,9 @@ void onMotorcycleHit(int snum, DDukeActor* victim)
p->MotoSpeed -= p->MotoSpeed / 4.;
p->TurbCount = 6;
}
else if ((victim->spr.picnum == RRTILE2431 || victim->spr.picnum == RRTILE2443 || victim->spr.picnum == RRTILE2451 || victim->spr.picnum == RRTILE2455)
&& !islockedactivator(victim) && p->MotoSpeed > 45)
else if (p->MotoSpeed > 45)
{
S_PlayActorSound(SQUISHED, victim);
if (victim->spr.picnum == RRTILE2431 || victim->spr.picnum == RRTILE2451)
{
if (victim->spr.lotag != 0)
{
DukeSpriteIterator it;
while (auto act2 = it.Next())
{
if ((act2->spr.picnum == RRTILE2431 || act2->spr.picnum == RRTILE2451) && act2->spr.pal == 4)
{
if (victim->spr.lotag == act2->spr.lotag)
{
act2->spr.scale = DVector2(0, 0);
}
}
}
}
fi.guts(victim, RRTILE2460, 12, myconnectindex);
fi.guts(victim, RRTILE2465, 3, myconnectindex);
}
else
fi.guts(victim, RRTILE2465, 3, myconnectindex);
fi.guts(victim, RRTILE2465, 3, myconnectindex);
victim->spr.scale = DVector2(0, 0);
CallOnMotoSmash(victim, p);
}
}
@ -3802,15 +3778,6 @@ HORIZONLY:
}
}
CallOnTouch(clip.actor(), p);
if (isRRRA())
{
if (clip.actor()->spr.picnum == RRTILE2443 && clip.actor()->spr.pal == 19)
{
clip.actor()->spr.pal = 0;
p->DrugMode = 5;
ps[snum].GetActor()->spr.extra = gs.max_player_health;
}
}
}
if (p->jetpack_on == 0)

View file

@ -1326,42 +1326,23 @@ void checkplayerhurt_r(player_struct* p, const Collision &coll)
{
if (coll.type == kHitSprite)
{
switch (coll.actor()->spr.picnum)
{
case RRTILE2430:
case RRTILE2431:
case RRTILE2432:
case RRTILE2443:
case RRTILE2446:
case RRTILE2451:
case RRTILE2455:
if (isRRRA() && p->hurt_delay2 < 8)
{
p->GetActor()->spr.extra -= 2;
p->hurt_delay2 = 16;
SetPlayerPal(p, PalEntry(32, 32, 0, 0));
S_PlayActorSound(DUKE_LONGTERM_PAIN, p->GetActor());
}
return;
default:
CallOnHurt(coll.actor(), p);
return;
}
CallOnHurt(coll.actor(), p);
return;
}
if (coll.type != kHitWall) return;
auto wal = coll.hitWall;
if (p->hurt_delay > 0) p->hurt_delay--;
else if (wal->cstat & (CSTAT_WALL_BLOCK | CSTAT_WALL_ALIGN_BOTTOM | CSTAT_WALL_MASKED | CSTAT_WALL_BLOCK_HITSCAN)) switch (wal->overpicnum)
if (coll.type == kHitWall)
{
case BIGFORCE:
p->hurt_delay = 26;
fi.checkhitwall(p->GetActor(), wal, p->GetActor()->getPosWithOffsetZ() + p->angle.ang.ToVector() * 2, -1);
break;
auto wal = coll.hitWall;
if (p->hurt_delay > 0) p->hurt_delay--;
else if (wal->cstat & (CSTAT_WALL_BLOCK | CSTAT_WALL_ALIGN_BOTTOM | CSTAT_WALL_MASKED | CSTAT_WALL_BLOCK_HITSCAN)) switch (wal->overpicnum)
{
case BIGFORCE:
p->hurt_delay = 26;
fi.checkhitwall(p->GetActor(), wal, p->GetActor()->getPosWithOffsetZ() + p->angle.ang.ToVector() * 2, -1);
break;
}
}
}
@ -1976,62 +1957,6 @@ void checkhitsprite_r(DDukeActor* targ, DDukeActor* proj)
}
}
break;
case RRTILE2431:
if (targ->spr.pal != 4)
{
targ->spr.picnum = RRTILE2451;
if (targ->spr.lotag != 0)
{
DukeSpriteIterator it;
while (auto act = it.Next())
{
if (act->spr.picnum == RRTILE2431 && act->spr.pal == 4)
{
if (targ->spr.lotag == act->spr.lotag)
act->spr.picnum = RRTILE2451;
}
}
}
}
break;
case RRTILE2443:
if (targ->spr.pal != 19)
targ->spr.picnum = RRTILE2455;
break;
case RRTILE2455:
S_PlayActorSound(SQUISHED, targ);
fi.guts(targ, RRTILE2465, 3, myconnectindex);
targ->Destroy();
break;
case RRTILE2451:
if (targ->spr.pal != 4)
{
S_PlayActorSound(SQUISHED, targ);
if (targ->spr.lotag != 0)
{
DukeSpriteIterator it;
while (auto act = it.Next())
{
if (act->spr.picnum == RRTILE2451 && act->spr.pal == 4)
{
if (targ->spr.lotag == act->spr.lotag)
{
fi.guts(targ, RRTILE2460, 12, myconnectindex);
fi.guts(targ, RRTILE2465, 3, myconnectindex);
act->spr.scale = DVector2(0, 0);
targ->spr.scale = DVector2(0, 0);
}
}
}
}
else
{
fi.guts(targ, RRTILE2460, 12, myconnectindex);
fi.guts(targ, RRTILE2465, 3, myconnectindex);
targ->spr.scale = DVector2(0, 0);
}
}
break;
case RRTILE2437:
S_PlayActorSound(439, targ);
break;

View file

@ -142,8 +142,6 @@ DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act, TArray<DDukeActor*>*
ChangeActorStat(act, 122);
break;
case RRTILE2460:
case RRTILE2465:
case BIKEJIBA:
case BIKEJIBB:
case BIKEJIBC:

View file

@ -51,6 +51,15 @@ int PicForName(int intname)
{
picnum = TileFiles.tileForName("FEATHER");
}
else if (FName(ENamedName(intname)) == FName("RedneckCactusDebris1"))
{
picnum = TileFiles.tileForName("CACTUSDEBRIS1");
}
else if (FName(ENamedName(intname)) == FName("RedneckCactusDebris2"))
{
picnum = TileFiles.tileForName("CACTUSDEBRIS2");
}
return picnum;
}
@ -341,7 +350,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, lotsofstuff, DukeActor_Lotsofstuff)
return 0;
}
void DukeActor_spawnguts(DDukeActor* actor, int count, int intname)
void DukeActor_spawnguts(DDukeActor* actor, int intname, int count)
{
int picnum = PicForName(intname);
fi.guts(actor, picnum, count, myconnectindex);
@ -352,7 +361,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, spawnguts, DukeActor_spawnguts)
PARAM_SELF_PROLOGUE(DDukeActor);
PARAM_INT(type);
PARAM_INT(count);
DukeActor_spawnguts(self, count, type);
DukeActor_spawnguts(self, type, count);
return 0;
}
@ -372,6 +381,24 @@ DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, movesprite, DukeActor_movesprite)
ACTION_RETURN_INT(DukeActor_movesprite(self, velx, vely, velz, clipmask));
}
int DukeActor_jibs(DDukeActor* actor, int jib6mode, int timeout, int callsetsprite, int floorcheck, int zcheck1, int zcheck2)
{
return jibs(actor, -1 /* fixme*/, timeout, callsetsprite, floorcheck, zcheck1, zcheck2);
}
DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, jibs, DukeActor_jibs)
{
PARAM_SELF_PROLOGUE(DDukeActor);
PARAM_INT(jib6mode);
PARAM_INT(timeout);
PARAM_INT(callsetsprite);
PARAM_INT(floorcheck);
PARAM_INT(zcheck1);
PARAM_INT(zcheck2);
ACTION_RETURN_INT(DukeActor_jibs(self, jib6mode, timeout, callsetsprite, floorcheck, zcheck1, zcheck2));
}
DDukeActor* DukeActor_Spawnsprite(DDukeActor* origin, int picnum)
{
if (picnum >= 0 && picnum < MAXTILES)

View file

@ -1,4 +1,13 @@
spawnclasses
{
2430 = RedneckCactusLargeYellow
2431 = RedneckCactusLargeGreen
2432 = RedneckCactusLargeBrown
2443 = RedneckCactusDrug
2451 = RedneckCactusWithHoles
2455 = RedneckCactusSmall
2446 = RedneckCactusLargeGreen2
2460 = RedneckCactusDebris1
2465 = RedneckCactusDebris2
7424 = RedneckRabbitSpawner
}

View file

@ -76,6 +76,7 @@ version "4.10"
#include "zscript/games/duke/actors/rabbitspawner.zs"
#include "zscript/games/duke/actors/chickenplant.zs"
#include "zscript/games/duke/actors/lumberblade.zs"
#include "zscript/games/duke/actors/rrcactus.zs"
#include "zscript/games/blood/bloodgame.zs"
#include "zscript/games/blood/ui/menu.zs"

View file

@ -0,0 +1,212 @@
class RedneckCactusLargeYellow : DukeActor
{
default
{
statnum STAT_ACTOR;
SpriteSet "CACTUSLARGEYELLOW";
}
override void onHurt(DukePlayer p)
{
if (p.hurt_delay2 < 8)
{
p.actor.extra -= 2;
p.hurt_delay2 = 16;
p.pals = Color(32, 32, 0, 0);
p.actor.PlayActorSound(RRSnd.LN_PAIN8);
}
}
}
class RedneckCactusLargeBrown : RedneckCactusLargeYellow
{
default
{
SpriteSet "CACTUSLARGEBROWN";
}
}
class RedneckCactusLargeGreen2 : RedneckCactusLargeYellow
{
default
{
SpriteSet "CACTUSLARGEGREEN2";
}
}
class RedneckCactusLargeGreen : RedneckCactusLargeYellow
{
default
{
SpriteSet "CACTUSLARGEGREEN", "CACTUSWITHHOLES";
}
override void onHit(DukeActor hitter)
{
if (self.SpriteSetIndex == 0)
{
if (self.pal != 4)
{
self.setSpriteSetImage(1);
if (self.lotag != 0)
{
DukeSpriteIterator it;
for(let act = it.First(); act; act = it.Next())
{
if (act is 'RedneckCactusLargeGreen' && act.spriteSetIndex == 0 && act.pal == 4)
{
if (self.lotag == act.lotag)
act.setSpriteSetImage(1);
}
}
}
}
}
else
{
if (self.pal != 4)
{
self.PlayActorSound(DukeSnd.SQUISHED);
if (self.lotag != 0)
{
DukeSpriteIterator it;
for(let act = it.First(); act; act = it.Next())
{
if (act is 'RedneckCactusLargeGreen' && act.spriteSetIndex == 1 && act.pal == 4)
{
if (self.lotag == act.lotag)
{
self.spawnguts('RedneckCactusDebris1', 12);
self.spawnguts('RedneckCactusDebris2', 3);
act.scale = (0, 0);
self.scale = (0, 0);
}
}
}
}
else
{
self.spawnguts('RedneckCactusDebris1', 12);
self.spawnguts('RedneckCactusDebris2', 3);
self.scale = (0, 0);
}
}
}
}
override void OnMotoSmash(DukePlayer hitter)
{
self.PlayActorSound(DukeSnd.SQUISHED);
if (self.lotag != 0)
{
DukeSpriteIterator it;
for(let act = it.First(); act; act = it.Next())
{
if (act is 'RedneckCactusLargeGreen' && act.pal == 4)
{
if (self.lotag == act.lotag)
{
act.scale = (0, 0);
}
}
}
}
self.spawnguts('RedneckCactusDebris1', 12);
self.spawnguts('RedneckCactusDebris2', 3);
self.scale = (0, 0);
}
}
class RedneckCactusWithHoles : RedneckCactusLargeGreen
{
default
{
SpriteSetIndex 1;
}
}
class RedneckCactusDrug : RedneckCactusLargeYellow
{
default
{
SpriteSet "CACTUSDRUG", "CACTUSSMALL";
}
override void onHit(DukeActor hitter)
{
if (self.spritesetIndex == 0 && self.pal != 19)
{
self.setSpriteSetImage(1);
}
else if (self.spritesetIndex == 1)
{
self.PlayActorSound(DukeSnd.SQUISHED);
self.spawnguts('RedneckCactusDebris2', 3);
self.Destroy();
}
}
override void onTouch(DukePlayer toucher)
{
if (self.spritesetindex == 0 && self.pal == 19)
{
self.pal = 0;
toucher.DrugMode = 5;
toucher.actor.extra = gs.max_player_health;
}
}
override void OnMotoSmash(DukePlayer hitter)
{
self.spawnguts('RedneckCactusDebris2', 3);
self.scale = (0, 0);
}
}
class RedneckCactusSmall : RedneckCactusDrug
{
default
{
SpriteSetIndex 1;
}
}
// ---------------------------------
class RedneckCactusDebris1 : DukeActor
{
default
{
statnum STAT_MISC;
pic "CACTUSDEBRIS1";
}
override void Tick()
{
if (!self.jibs(false, false, true, true, false, true)) return; // very poor API... Change this when jibs can be scriptified.
if (self.sector.lotag == 800 && self.pos.Z >= self.sector.floorz - 8)
self.Destroy();
}
override bool animate(tspritetype tspr)
{
if (tspr.pal == 6) tspr.shade = -120;
if (self.sector.shadedsector == 1)
tspr.shade = 16;
return true;
}
}
class RedneckCactusDebris2 : RedneckCactusDebris1
{
default
{
pic "CACTUSDEBRIS2";
}
}

View file

@ -178,6 +178,7 @@ class DukeActor : CoreActor native
virtual void onHurt(DukePlayer p) {}
virtual bool onUse(DukePlayer user) { return false; }
virtual void onTouch(DukePlayer toucher) {}
virtual void onMotoSmash(DukePlayer toucher) {}
virtual void onRespawn(int tag) { }
virtual bool animate(tspritetype tspr) { return false; }
virtual void RunState() {} // this is the CON function.
@ -192,6 +193,7 @@ class DukeActor : CoreActor native
native void lotsofstuff(Name type, int count);
native void spawnguts(Name type, int count);
native int movesprite(Vector3 move, int clipmask);
native bool jibs(bool jib6mode, bool timeout, bool callsetsprite, bool floorcheck, bool zcheck1, bool zcheck2);
// temporary flag accessors - need to be eliminated once we can have true actor flags