- scriptified RR's bowling stuff.

This commit is contained in:
Christoph Oelckers 2022-12-02 16:26:31 +01:00
parent 9ad8f67ce9
commit 5a155730b4
17 changed files with 456 additions and 499 deletions

View file

@ -24,6 +24,7 @@ xx(DukeGlassPieces)
xx(DukeGlassPieces1) xx(DukeGlassPieces1)
xx(DukeGlassPieces2) xx(DukeGlassPieces2)
xx(DukeNaturalLightning) xx(DukeNaturalLightning)
xx(RedneckBowlingPin)
xx(spawnstate) xx(spawnstate)
xx(brokenstate) xx(brokenstate)

View file

@ -465,6 +465,15 @@ DEFINE_ACTION_FUNCTION_NATIVE(_sectortype, getslopes, sector_getslopes)
return min(numret, 2); return min(numret, 2);
} }
DEFINE_ACTION_FUNCTION_NATIVE(_sectortype, nextsectorneighborz, nextsectorneighborzptr)
{
PARAM_SELF_STRUCT_PROLOGUE(sectortype);
PARAM_FLOAT(z);
PARAM_INT(find);
ACTION_RETURN_POINTER(nextsectorneighborzptr(self, z, find));
}
//============================================================================= //=============================================================================
void wall_setxpan(walltype* wal, double val) void wall_setxpan(walltype* wal, double val)

View file

@ -37,14 +37,6 @@ BEGIN_DUKE_NS
void dojaildoor(); void dojaildoor();
void moveminecart(); void moveminecart();
void ballreturn(DDukeActor* spr);
void pinsectorresetdown(sectortype* sect);
int pinsectorresetup(sectortype* sect);
int checkpins(sectortype* sect);
void resetpins(sectortype* sect);
void resetlanepics(void);
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// //
@ -1191,34 +1183,9 @@ void rr_specialstats()
tickstat(STAT_CHICKENPLANT); tickstat(STAT_CHICKENPLANT);
} }
DukeStatIterator it(STAT_BOWLING); tickstat(STAT_BOWLING);
while (auto act = it.Next())
{
if (act->spr.picnum == BOWLINGPINSPOT)
if (act->spr.lotag == 100)
{
auto pst = pinsectorresetup(act->sector());
if (pst)
{
act->spr.lotag = 0;
if (act->spr.extra == 1)
{
pst = checkpins(act->sector());
if (!pst)
{
act->spr.extra = 2;
}
}
if (act->spr.extra == 2)
{
act->spr.extra = 0;
resetpins(act->sector());
}
}
}
}
it.Reset(STAT_TELEPORT); DukeStatIterator it(STAT_TELEPORT);
while (auto act = it.Next()) while (auto act = it.Next())
{ {
if (act->spr.picnum == RRTELEPORT) if (act->spr.picnum == RRTELEPORT)
@ -1254,91 +1221,6 @@ void rr_specialstats()
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
static int henstand(DDukeActor *actor)
{
if (actor->spr.picnum == HENSTAND || actor->spr.picnum == HENSTAND + 1)
{
actor->spr.lotag--;
if (actor->spr.lotag == 0)
{
spawn(actor, HEN);
actor->spr.scale.Zero();
ChangeActorStat(actor, STAT_MISC);
return 1;
}
}
if (actor->sector()->lotag == 900)
actor->vel.X = 0;
if(actor->vel.X != 0)
{
makeitfall(actor);
Collision coll;
movesprite_ex(actor, DVector3(actor->spr.Angles.Yaw.ToVector() * actor->vel.X, actor->vel.Z), CLIPMASK0, coll);
if (coll.type)
{
if (coll.type == kHitWall)
{
DAngle k = coll.hitWall->delta().Angle();
actor->spr.Angles.Yaw = k * 2 - actor->spr.Angles.Yaw;
}
else if (coll.type == kHitSprite)
{
auto hitact = coll.actor();
fi.checkhitsprite(actor, hitact);
if (hitact->spr.picnum == HEN)
{
auto ns = spawn(hitact, HENSTAND);
hitact->spr.scale.Zero();
ChangeActorStat(hitact, STAT_MISC);
if (ns)
{
ns->vel.X = 2;
ns->spr.lotag = 40;
ns->spr.Angles.Yaw = actor->spr.Angles.Yaw;
}
}
}
}
actor->vel.X -= 1/16.;
if(actor->vel.X < 0) actor->vel.X = 0;
actor->spr.cstat = CSTAT_SPRITE_BLOCK_ALL;
if (actor->spr.picnum == BOWLINGPIN)
{
actor->spr.cstat |= CSTAT_SPRITE_XFLIP & ESpriteFlags::FromInt(int(actor->vel.X * 16));
actor->spr.cstat |= CSTAT_SPRITE_YFLIP & ESpriteFlags::FromInt(int(actor->vel.X * 16));
if (krand() & 1)
actor->spr.picnum = BOWLINGPIN + 1;
}
else if (actor->spr.picnum == HENSTAND)
{
actor->spr.cstat |= CSTAT_SPRITE_XFLIP & ESpriteFlags::FromInt(int(actor->vel.X * 16));
actor->spr.cstat |= CSTAT_SPRITE_YFLIP & ESpriteFlags::FromInt(int(actor->vel.X * 16));
if (krand() & 1)
actor->spr.picnum = HENSTAND + 1;
if (actor->vel.X == 0)
return 2;//actor->Destroy(); still needs to run a script but should not do on a deleted object
}
if (actor->spr.picnum == BOWLINGPIN || (actor->spr.picnum == BOWLINGPIN + 1 && actor->vel.X == 0))
{
return 2;//actor->Destroy(); still needs to run a script but should not do on a deleted object
}
}
else if (actor->sector()->lotag == 900)
{
if (actor->spr.picnum == BOWLINGBALL)
ballreturn(actor);
actor->Destroy();
return 1;
}
return 0;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void moveactors_r(void) void moveactors_r(void)
{ {
double xx; double xx;
@ -1374,34 +1256,6 @@ void moveactors_r(void)
} }
else switch(act->spr.picnum) else switch(act->spr.picnum)
{ {
case BOWLINGBALL:
if (act->vel.X != 0)
{
if(!S_CheckSoundPlaying(356))
S_PlayActorSound(356,act);
}
else
{
spawn(act,BOWLINGBALLSPRITE);
act->Destroy();
continue;
}
if (act->sector()->lotag == 900)
{
S_StopSound(356, nullptr);
}
[[fallthrough]];
case BOWLINGPIN:
case BOWLINGPIN+1:
case HENSTAND:
case HENSTAND+1:
{
int todo = henstand(act);
if (todo == 2) deleteafterexecute = true;
if (todo == 1) continue;
break;
}
case EMPTYBIKE: case EMPTYBIKE:
if (!isRRRA()) break; if (!isRRRA()) break;
makeitfall(act); makeitfall(act);
@ -2175,7 +2029,7 @@ static int fallspecial(DDukeActor *actor, int playernum)
} }
if (actor->sector()->lotag == 800) if (actor->sector()->lotag == 800)
{ {
if (actor->spr.picnum == 40) if (actor->spr.picnum == AMMO)
{ {
addspritetodelete(); addspritetodelete();
return 0; return 0;

View file

@ -34,275 +34,29 @@ Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms
BEGIN_DUKE_NS BEGIN_DUKE_NS
void ballreturn(DDukeActor *ball) void updatepindisplay(int tag, int pins)
{ {
DukeStatIterator it(STAT_BOWLING); static const uint8_t pinx[] = { 64, 56, 72, 48, 64, 80, 40, 56, 72, 88 };
while (auto act = it.Next()) static const uint8_t piny[] = { 48, 40, 40, 32, 32, 32, 24, 24, 24, 24 };
if (tag < 1 || tag > 4) return;
tag += BOWLINGLANE1 - 1;
if (TileFiles.tileMakeWritable(tag))
{ {
if (act->spr.picnum == RRTILE281 && ball->sector() == act->sector()) tileCopySection(LANEPICBG, 0, 0, 128, 64, tag, 0, 0);
{ for (int i = 0; i < 10; i++) if (pins & (1 << i))
DukeStatIterator it2(STAT_BOWLING); tileCopySection(LANEPICS, 0, 0, 8, 8, tag, pinx[i] - 4, piny[i] - 10);
while (auto act2 = it2.Next())
{
if (act2->spr.picnum == BOWLINGBALLSPOT && act->spr.hitag == act2->spr.hitag)
spawn(act2, BOWLINGBALLSPRITE);
if (act2->spr.picnum == BOWLINGPINSPOT && act->spr.hitag == act2->spr.hitag && act2->spr.lotag == 0)
{
act2->spr.lotag = 100;
act2->spr.extra++;
pinsectorresetdown(act2->sector());
}
}
}
}
}
void pinsectorresetdown(sectortype* sec)
{
int j = getanimationindex(anim_ceilingz, sec);
if (j == -1)
{
setanimation(sec, anim_ceilingz, sec, sec->floorz, 0.25);
}
}
int pinsectorresetup(sectortype* sec)
{
int j = getanimationindex(anim_ceilingz, sec);
if (j == -1)
{
double z = nextsectorneighborzptr(sec, sec->ceilingz, Find_CeilingUp | Find_Safe)->ceilingz;
setanimation(sec, anim_ceilingz, sec, z, 0.25);
return 1;
}
return 0;
}
int checkpins(sectortype* sect)
{
int x, y;
bool pins[10] = {};
int tag = 0;
int pin = 0;
DukeSectIterator it(sect);
while (auto a2 = it.Next())
{
if (a2->spr.picnum == BOWLINGPIN)
{
pin++;
pins[a2->spr.lotag] = true;
}
if (a2->spr.picnum == BOWLINGPINSPOT)
{
tag = a2->spr.hitag;
}
}
if (tag)
{
tag += LANEPICS + 1;
TileFiles.tileMakeWritable(tag);
tileCopySection(LANEPICS + 1, 0, 0, 128, 64, tag, 0, 0);
for (int i = 0; i < 10; i++)
{
if (pins[i])
{
switch (i)
{
default:
case 0:
x = 64;
y = 48;
break;
case 1:
x = 56;
y = 40;
break;
case 2:
x = 72;
y = 40;
break;
case 3:
x = 48;
y = 32;
break;
case 4:
x = 64;
y = 32;
break;
case 5:
x = 80;
y = 32;
break;
case 6:
x = 40;
y = 24;
break;
case 7:
x = 56;
y = 24;
break;
case 8:
x = 72;
y = 24;
break;
case 9:
x = 88;
y = 24;
break;
}
tileCopySection(LANEPICS, 0, 0, 8, 8, tag, x - 4, y - 10);
}
}
}
return pin;
}
void resetpins(sectortype* sect)
{
int i, tag = 0;
int x, y;
DukeSectIterator it(sect);
while (auto a2 = it.Next())
{
if (a2->spr.picnum == BOWLINGPIN)
a2->Destroy();
}
it.Reset(sect);
while (auto a2 = it.Next())
{
if (a2->spr.picnum == 283)
{
auto spawned = spawn(a2, BOWLINGPIN);
if (spawned)
{
spawned->spr.lotag = a2->spr.lotag;
spawned->clipdist = 12; // random formula here was bogus and always produced 48.
spawned->spr.Angles.Yaw -= DAngle22_5 * 0.125 * (((krand() & 32) - (krand() & 64)) >> 5); // weird formula to preserve number of krand calls.
}
}
if (a2->spr.picnum == 280)
tag = a2->spr.hitag;
}
if (tag)
{
tag += LANEPICS + 1;
TileFiles.tileMakeWritable(tag);
tileCopySection(LANEPICS + 1, 0, 0, 128, 64, tag, 0, 0);
for (i = 0; i < 10; i++)
{
switch (i)
{
default:
case 0:
x = 64;
y = 48;
break;
case 1:
x = 56;
y = 40;
break;
case 2:
x = 72;
y = 40;
break;
case 3:
x = 48;
y = 32;
break;
case 4:
x = 64;
y = 32;
break;
case 5:
x = 80;
y = 32;
break;
case 6:
x = 40;
y = 24;
break;
case 7:
x = 56;
y = 24;
break;
case 8:
x = 72;
y = 24;
break;
case 9:
x = 88;
y = 24;
break;
}
tileCopySection(LANEPICS, 0, 0, 8, 8, tag, x - 4, y - 10);
}
} }
} }
void resetlanepics(void) void resetlanepics(void)
{ {
if (!isRR()) return; if (!isRR()) return;
int x, y;
for (int tag = 0; tag < 4; tag++) for (int tag = 0; tag < 4; tag++)
{ {
int pic = tag + 1; int pic = tag + 1;
if (pic == 0) continue; if (pic == 0) continue;
pic += LANEPICS + 1; updatepindisplay(pic, 0xffff);
TileFiles.tileMakeWritable(pic);
tileCopySection(LANEPICS + 1, 0, 0, 128, 64, pic, 0, 0);
for (int i = 0; i < 10; i++)
{
switch (i)
{
default:
case 0:
x = 64;
y = 48;
break;
case 1:
x = 56;
y = 40;
break;
case 2:
x = 72;
y = 40;
break;
case 3:
x = 48;
y = 32;
break;
case 4:
x = 64;
y = 32;
break;
case 5:
x = 80;
y = 32;
break;
case 6:
x = 40;
y = 24;
break;
case 7:
x = 56;
y = 24;
break;
case 8:
x = 72;
y = 24;
break;
case 9:
x = 88;
y = 24;
break;
}
tileCopySection(LANEPICS, 0, 0, 8, 8, pic, x - 4, y - 10);
}
} }
} }

View file

@ -351,7 +351,7 @@ void displayweapon_r(int snum, double interpfrac)
if (p->ammo_amount[BOWLING_WEAPON]) if (p->ammo_amount[BOWLING_WEAPON])
{ {
hud_drawpal(weapon_xoffset + 162 - look_anghalf, hud_drawpal(weapon_xoffset + 162 - look_anghalf,
looking_arc + 214 - gun_pos + (*kb << 3), BOWLINGBALLH, shade, o, pal); looking_arc + 214 - gun_pos + (*kb << 3), BOWLINGBALLHUD, shade, o, pal);
} }
else else
{ {

View file

@ -173,10 +173,10 @@ x(WALLLIGHTBUST2, 249)
x(LIGHTSWITCH2, 250) x(LIGHTSWITCH2, 250)
x(LIGHTSWITCH2ON, 251) x(LIGHTSWITCH2ON, 251)
x(UFOBEAM, 252) x(UFOBEAM, 252)
y(BOWLINGPINSPOT, 280) y(BOWLINGPINCTRL, 280)
y(RRTILE281, 281) y(BOWLINGSECTORLINK, 281)
y(BOWLINGBALLSPOT, 282) y(BOWLINGBALLSPOT, 282)
y(RRTILE283, 283) y(BOWLINGPINSPOT, 283)
x(CHICKENASPAWN, 285) x(CHICKENASPAWN, 285)
x(CHICKENCSPAWN, 286) x(CHICKENCSPAWN, 286)
x(FEATHERSPAWN, 287) x(FEATHERSPAWN, 287)
@ -664,10 +664,11 @@ y(RRTILE2005, 2005)
x(POPCORN, 2021) x(POPCORN, 2021)
y(RRTILE2022, 2022) y(RRTILE2022, 2022)
x(LANEPICS, 2023) x(LANEPICS, 2023)
y(RRTILE2025, 2025) x(LANEPICBG, 2024)
y(RRTILE2026, 2026) x(BOWLINGLANE1, 2025)
y(RRTILE2027, 2027) x(BOWLINGLANE2, 2026)
y(RRTILE2028, 2028) x(BOWLINGLANE3, 2027)
x(BOWLINGLANE4, 2028)
y(RRTILE2034, 2034) y(RRTILE2034, 2034)
y(RRTILE2050, 2050) y(RRTILE2050, 2050)
y(RRTILE2052, 2052) y(RRTILE2052, 2052)
@ -1014,11 +1015,12 @@ x(FIRELASER3, 3422)
x(FIRELASER4, 3423) x(FIRELASER4, 3423)
x(FIRELASER5, 3424) x(FIRELASER5, 3424)
x(FIRELASER6, 3425) x(FIRELASER6, 3425)
x(BOWLINGBALLH, 3428) x(BOWLINGBALLHUD, 3428)
x(BOWLINGBALL, 3430) x(BOWLINGBALL, 3430)
x(BOWLINGBALLSPRITE, 3437) x(BOWLINGBALLSPRITE, 3437)
x(POWDERH, 3438) x(POWDERH, 3438)
x(BOWLINGPIN, 3440) x(BOWLINGPIN, 3440)
x(BOWLINGPIN1, 3441)
x(DEVISTATOR, 3445) x(DEVISTATOR, 3445)
x(RPGGUN, 3452) x(RPGGUN, 3452)
y(RRTILE3462, 3462) y(RRTILE3462, 3462)
@ -1452,6 +1454,7 @@ x(SBDIE, 4820)
x(HEN, 4861) x(HEN, 4861)
x(HENSTAYPUT, 4862) x(HENSTAYPUT, 4862)
x(HENSTAND, 4897) x(HENSTAND, 4897)
x(HENSTAND1, 4898)
x(PIG, 4945) x(PIG, 4945)
x(PIGSTAYPUT, 4946) x(PIGSTAYPUT, 4946)
x(PIGEAT, 4983) x(PIGEAT, 4983)

View file

@ -838,17 +838,6 @@ void shoot_r(DDukeActor* actor, int atwith, PClass* cls)
} }
break; break;
} }
case BOWLINGBALL:
{
auto j = spawn(actor, atwith);
if (j)
{
j->vel.X = 250 / 16.;
j->spr.Angles.Yaw = actor->spr.Angles.Yaw;
j->spr.pos.Z -= 15;
}
break;
}
case OWHIP: case OWHIP:
case UWHIP: case UWHIP:
shootwhip(actor, p, spos, sang, atwith); shootwhip(actor, p, spos, sang, atwith);

View file

@ -1448,40 +1448,6 @@ void checkhitsprite_r(DDukeActor* targ, DDukeActor* proj)
if (spawned) spawned->spriteextra = Scrap6 + (krand() & 15); if (spawned) spawned->spriteextra = Scrap6 + (krand() & 15);
} }
break; break;
case BOWLINGBALL:
proj->vel.X = targ->vel.X * 0.75;
if (krand() & 16) proj->spr.Angles.Yaw -= DAngle22_5 / 8;
S_PlayActorSound(355, targ);
break;
case BOWLINGPIN:
case BOWLINGPIN + 1:
case HENSTAND:
case HENSTAND + 1:
if (proj->spr.picnum == BOWLINGPIN || proj->spr.picnum == BOWLINGPIN + 1)
{
proj->vel.X *= 0.75;
proj->spr.Angles.Yaw -= targ->spr.Angles.Yaw * 2 + randomAngle(11.25);
targ->spr.Angles.Yaw += randomAngle(22.5 / 8);
S_PlayActorSound(355, targ);
}
else if (proj->spr.picnum == HENSTAND || proj->spr.picnum == HENSTAND + 1)
{
proj->vel.X *= 0.75;
proj->spr.Angles.Yaw -= targ->spr.Angles.Yaw * 2 + randomAngle(22.5 / 8);
targ->spr.Angles.Yaw += randomAngle(22.5 / 8);
S_PlayActorSound(355, targ);
}
else
{
if (krand() & 3)
{
targ->vel.X = 10.25;
targ->spr.Angles.Yaw = proj->spr.Angles.Yaw;
}
}
break;
case FANSPRITE: case FANSPRITE:
targ->spr.picnum = FANSPRITEBROKE; targ->spr.picnum = FANSPRITEBROKE;
targ->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL; targ->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL;

View file

@ -56,21 +56,6 @@ DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act, TArray<DDukeActor*>*
default_case: default_case:
spawninitdefault(actj, act); spawninitdefault(actj, act);
break; break;
case BOWLINGPINSPOT:
case RRTILE281:
case BOWLINGBALLSPOT:
case RRTILE283:
case RRTILE2025:
case RRTILE2026:
case RRTILE2027:
case RRTILE2028:
act->spr.cstat = 0;
act->spr.cstat |= CSTAT_SPRITE_INVISIBLE;
act->spr.scale = DVector2(0, 0);
act->clipdist = 0;
act->spr.extra = 0;
ChangeActorStat(act, STAT_BOWLING);
break;
case RRTILE8450: case RRTILE8450:
if (!isRRRA()) goto default_case; if (!isRRRA()) goto default_case;
act->spr.scale = DVector2(1, 1); act->spr.scale = DVector2(1, 1);
@ -172,30 +157,12 @@ DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act, TArray<DDukeActor*>*
act->clipdist = 8; act->clipdist = 8;
ChangeActorStat(act, STAT_ZOMBIEACTOR); ChangeActorStat(act, STAT_ZOMBIEACTOR);
break; break;
case BOWLINGBALL:
act->spr.cstat = CSTAT_SPRITE_BLOCK_HITSCAN;
act->clipdist = 16;
act->spr.scale = DVector2(0.171875, 0.140625);
ChangeActorStat(act, STAT_ZOMBIEACTOR);
break;
case HENSTAND:
act->spr.cstat = CSTAT_SPRITE_BLOCK_ALL;
act->clipdist = 12;
act->spr.scale = DVector2(0.328125, 0.234375);
ChangeActorStat(act, STAT_ZOMBIEACTOR);
break;
case RRTELEPORT: case RRTELEPORT:
case RRTELEPORTDEST: case RRTELEPORTDEST:
act->spr.scale = DVector2(1, 1); act->spr.scale = DVector2(1, 1);
act->clipdist = 16; act->clipdist = 16;
ChangeActorStat(act, STAT_TELEPORT); ChangeActorStat(act, STAT_TELEPORT);
break; break;
case BOWLINGPIN:
act->spr.cstat = CSTAT_SPRITE_BLOCK_ALL;
act->clipdist = 12;
act->spr.scale = DVector2(0.359375, 0.359375);
ChangeActorStat(act, STAT_ZOMBIEACTOR);
break;
case DUKELYINGDEAD: case DUKELYINGDEAD:
if (actj && actj->isPlayer()) if (actj && actj->isPlayer())
{ {
@ -420,7 +387,6 @@ DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act, TArray<DDukeActor*>*
break; break;
case HEN: case HEN:
case HENSTAYPUT: case HENSTAYPUT:
case HENSTAND:
if (act->spr.pal == 35) if (act->spr.pal == 35)
{ {
act->spr.scale = DVector2(0.65625, 0.46875); act->spr.scale = DVector2(0.65625, 0.46875);

View file

@ -30,6 +30,7 @@ int PicForName(int intname)
{"DukePigCop", "PIGCOP"}, {"DukePigCop", "PIGCOP"},
{"DukeSmallSmoke", "SMALLSMOKE"}, {"DukeSmallSmoke", "SMALLSMOKE"},
{"DukeBurning", "BURNING"}, {"DukeBurning", "BURNING"},
{"RedneckBowlingBallSprite", "BOWLINGBALLSPRITE"},
}; };
for (auto& p : classes) for (auto& p : classes)
@ -176,6 +177,16 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Duke, badguyID, badguypic)
ACTION_RETURN_INT(badguypic(p)); ACTION_RETURN_INT(badguypic(p));
} }
void updatepindisplay(int tag, int pins);
DEFINE_ACTION_FUNCTION_NATIVE(_Duke, updatepindisplay, updatepindisplay)
{
PARAM_PROLOGUE;
PARAM_INT(tag);
PARAM_INT(mask);
updatepindisplay(tag, mask);
return 0;
}
DEFINE_GLOBAL_UNSIZED(dlevel) DEFINE_GLOBAL_UNSIZED(dlevel)
DEFINE_GLOBAL(camsprite) DEFINE_GLOBAL(camsprite)
@ -728,6 +739,13 @@ DEFINE_ACTION_FUNCTION(DDukeActor, attackerflag2)
ACTION_RETURN_BOOL(!!attackerflag(self, EDukeFlags2::FromInt(mask))); ACTION_RETURN_BOOL(!!attackerflag(self, EDukeFlags2::FromInt(mask)));
} }
DEFINE_ACTION_FUNCTION(DDukeActor, checktype) // for temporary checking of types that haven't been ported yet.
{
PARAM_SELF_PROLOGUE(DDukeActor);
PARAM_STRING(name);
ACTION_RETURN_BOOL(self->spr.picnum == TileFiles.tileForName(name));
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
@ -1363,6 +1381,24 @@ DEFINE_ACTION_FUNCTION_NATIVE(_DukeLevel, LocateTheLocator, LocateTheLocator)
ACTION_RETURN_POINTER(LocateTheLocator(tag, sect)); ACTION_RETURN_POINTER(LocateTheLocator(tag, sect));
} }
DEFINE_ACTION_FUNCTION_NATIVE(_DukeLevel, getanimationindex, getanimationindex)
{
PARAM_PROLOGUE;
PARAM_INT(tag);
PARAM_POINTER(sect, sectortype);
ACTION_RETURN_INT(getanimationindex(tag, sect));
}
DEFINE_ACTION_FUNCTION_NATIVE(_DukeLevel, setanimation, static_cast<int(*)(sectortype*, int, sectortype*, double, double)>(setanimation))
{
PARAM_PROLOGUE;
PARAM_POINTER(asect, sectortype);
PARAM_INT(tag);
PARAM_POINTER(sect, sectortype);
PARAM_FLOAT(dest);
PARAM_FLOAT(vel);
ACTION_RETURN_INT(setanimation(asect, tag, sect, dest, vel));
}
DEFINE_FIELD_X(DukeGameInfo, DukeGameInfo, max_ammo_amount); DEFINE_FIELD_X(DukeGameInfo, DukeGameInfo, max_ammo_amount);
DEFINE_FIELD_X(DukeGameInfo, DukeGameInfo, playerfriction); DEFINE_FIELD_X(DukeGameInfo, DukeGameInfo, playerfriction);

View file

@ -132,6 +132,13 @@ spawnclasses
5602 = RedneckCootJibA 5602 = RedneckCootJibA
5607 = RedneckCootJibB 5607 = RedneckCootJibB
5616 = RedneckCootJibB 5616 = RedneckCootJibB
280 = RedneckBowlingPinController
281 = RedneckBowlingSectorLink
282 = RedneckBowlingBallSpot
283 = RedneckBowlingPinSpot
3440 = RedneckBowlingPin
3430 = RedneckBowlingBall
4897 = RedneckHenstand
3114 = DukeGenericDestructible, "RRTILE3114", "RRTILE3117", "GLASS_BREAKING", spawnglass 3114 = DukeGenericDestructible, "RRTILE3114", "RRTILE3117", "GLASS_BREAKING", spawnglass
2876 = DukeGenericDestructible, "RRTILE2876", "RRTILE2990", "GLASS_BREAKING", spawnglass 2876 = DukeGenericDestructible, "RRTILE2876", "RRTILE2990", "GLASS_BREAKING", spawnglass

View file

@ -101,6 +101,7 @@ version "4.10"
#include "zscript/games/duke/actors/redneckmisc.zs" #include "zscript/games/duke/actors/redneckmisc.zs"
#include "zscript/games/duke/actors/bowling.zs"
#include "zscript/games/duke/actors/rabbitspawner.zs" #include "zscript/games/duke/actors/rabbitspawner.zs"
#include "zscript/games/duke/actors/chickenplant.zs" #include "zscript/games/duke/actors/chickenplant.zs"
#include "zscript/games/duke/actors/lumberblade.zs" #include "zscript/games/duke/actors/lumberblade.zs"

View file

@ -0,0 +1,338 @@
class RedneckBowlingPin : DukeActor
{
default
{
statnum STAT_ZOMBIEACTOR;
clipdist 12;
scaleX 0.359375;
scaleY 0.359375;
detail 0;
spriteset "BOWLINGPIN", "BOWLINGPIN1";
}
override void Initialize()
{
self.cstat |= CSTAT_SPRITE_BLOCK_ALL;
}
protected void DoTick(int type)
{
if (self.sector.lotag == 900)
self.vel.X = 0;
if(self.vel.X != 0)
{
self.makeitfall();
CollisionData coll;
self.movesprite_ex((self.angle.ToVector() * self.vel.X, self.vel.Z), CLIPMASK0, coll);
if (coll.type)
{
if (coll.type == kHitWall)
{
double k = coll.hitWall().delta().Angle();
self.angle = k * 2 - self.angle;
}
else if (coll.type == kHitSprite)
{
let hitact = DukeActor(coll.hitActor());
// avoid checkhitsprite here. The way this was handled was just wrong on all accounts
self.collide(hitact);
//if (hitact is "RedneckHen") // does not work yet - Hen is not scriptified.
if (hitact.checkType("HEN")) // Temporary workaround
{
let ns = hitact.spawn("RedneckHenstand");
hitact.scale = (0,0);
hitact.ChangeStat(STAT_MISC);
if (ns)
{
ns.vel.X = 2;
ns.lotag = 40;
ns.angle = self.angle;
}
}
}
}
self.vel.X -= 1/16.;
if(self.vel.X < 0) self.vel.X = 0;
self.cstat = CSTAT_SPRITE_BLOCK_ALL;
if (type < 2 && self.vel.X > 0)
{
self.cstat |= CSTAT_SPRITE_XFLIP & int(self.vel.X * 16);
self.cstat |= CSTAT_SPRITE_YFLIP & int(self.vel.X * 16);
if (random(0, 1)) self.setSpritesetImage(1);
}
if (type < 2 && self.vel.X == 0)
{
return;
}
}
else if (self.sector.lotag == 900 && type != 2)
{
self.Destroy();
}
}
override void Tick()
{
DoTick(0);
}
virtual void collide(DukeActor targa)
{
let targ = RedneckBowlingPin(targa);
if (!targ) return;
if (targ.detail == 0)
{
self.vel.X *= 0.75;
self.angle -= targ.angle * 2 + frandom(0, 11.25);
targ.angle += frandom(0, 22.5 / 8);
targ.PlayActorSound("BOWLPIN");
}
else if (targ.detail == 1)
{
self.vel.X *= 0.75;
self.angle -= targ.angle * 2 + frandom(0, 22.5 / 8);
targ.angle += frandom(0, 22.5 / 8);
targ.PlayActorSound("BOWLPIN");
}
}
override void onHit(DukeActor hitter)
{
if (random(0, 3))
{
self.vel.X = 10.25;
self.angle = hitter.angle;
}
}
}
// chickens on the bowling lane...
class RedneckHenstand : RedneckBowlingPin
{
default
{
scaleY 0.234375;
spriteset "HENSTAND", "HENSTAND1";
detail 1;
}
override void Tick()
{
self.lotag--;
if (self.lotag == 0)
{
self.spawn("RedneckHen");
self.scale = (0,0);
self.ChangeStat(STAT_MISC);
return;
}
DoTick(1);
}
}
class RedneckBowlingBall : RedneckBowlingPin
{
default
{
clipdist 17;
scaleX 0.171875;
scaleY 0.140625;
statnum STAT_ACTOR;
pic "BOWLINGBALL";
detail 2;
}
override void Tick()
{
if (self.vel.X != 0)
{
if(!Duke.CheckSoundPlaying("BOWLLOOP"))
self.PlayActorSound("BOWLLOOP");
}
else
{
self.spawn("RedneckBowlingBallSprite");
self.Destroy();
return;
}
if (self.sector.lotag == 900)
{
self.StopSound("BOWLLOOP");
}
DoTick(2);
if (self.sector.lotag == 900)
{
self.ballreturn();
self.Destroy();
return;
}
}
private void ballreturn()
{
DukeStatIterator it;
for (let act1 = it.First(STAT_BOWLING); act1; act1 = it.Next())
{
if (act1.getClassName() == 'RedneckBowlingSectorLink' && self.sector == act1.sector)
{
DukeStatIterator it2;
for (let act2 = it2.First(STAT_BOWLING); act2; act2 = it2.Next())
{
if (act2.getClassName() == 'RedneckBowlingBallSpot' && act1.hitag == act2.hitag)
{
act2.spawn("RedneckBowlingBallSprite");
}
if (act2.getClassName() == 'RedneckBowlingPinController' && act1.hitag == act2.hitag && act2.lotag == 0)
{
let sec = act2.sector;
act2.lotag = 100;
act2.extra++;
int j = dlevel.getanimationindex(dlevel.anim_ceilingz, sec);
if (j == -1)
dlevel.setanimation(sec, dlevel.anim_ceilingz, sec, sec.floorz, 0.25);
}
}
}
}
}
override void onHit(DukeActor hitter)
{
}
override void collide(DukeActor targ)
{
targ.vel.X = self.vel.X * 0.75;
if (random(0, 32767) & 16) targ.angle -= 22.5 / 8;
targ.PlayActorSound("BOWLPIN");
}
override bool ShootThis(DukeActor actor, DukePlayer plr, Vector3 spos, double sang)
{
let j = actor.spawn(self.GetClassName());
if (j)
{
j.vel.X = 250 / 16.;
j.angle = self.angle;
j.pos.Z -= 15;
}
return true;
}
}
class RedneckBowlingController : DukeActor
{
default
{
statnum STAT_BOWLING;
scaleX 0;
scaleY 0;
clipdist 0;
extra 0;
}
override void Initialize()
{
self.cstat = CSTAT_SPRITE_INVISIBLE;
}
}
class RedneckBowlingPinController : RedneckBowlingController
{
override void Tick()
{
if (self.lotag == 100)
{
let pst = pinsectorresetup();
if (pst)
{
self.lotag = 0;
if (self.extra == 1)
{
pst = checkpins();
if (!pst)
{
self.extra = 2;
}
}
if (self.extra == 2)
{
self.extra = 0;
resetpins();
}
}
}
}
int pinsectorresetup()
{
let sec = self.sector;
int j = dlevel.getanimationindex(dlevel.anim_ceilingz, sec);
if (j == -1)
{
double z = sec.nextsectorneighborz(sec.ceilingz, sectortype.Find_CeilingUp | sectortype.Find_Safe).ceilingz;
dlevel.setanimation(sec, dlevel.anim_ceilingz, sec, z, 0.25);
return 1;
}
return 0;
}
int checkpins()
{
int pins = 0;
int pin = 0;
DukeSectIterator it;
for (let a2 = it.First(self.sector); a2; a2 = it.Next())
{
if (a2.GetClassName() == 'RedneckBowlingPin' && a2.spritesetindex == 0)
{
pin++;
pins |= 1 << a2.lotag;
}
}
Duke.updatepindisplay(self.hitag, pins);
return pin;
}
void resetpins()
{
int i, tag = 0;
DukeSectIterator it;
for (let a2 = it.First(self.sector); a2; a2 = it.Next())
{
if (a2.GetClassName() == 'RedneckBowlingPin')
a2.Destroy();
}
for (let a2 = it.First(self.sector); a2; a2 = it.Next())
{
if (a2.GetClassName() == 'RedneckBowlingPinSpot')
{
let spawned = a2.spawn('RedneckBowlingPin');
if (spawned)
{
spawned.lotag = a2.lotag;
spawned.clipdist = 12; // random formula here was bogus and always produced 48.
spawned.angle -= 22.5 * 0.125 * (((random(0, 32767) & 32) - (random(0, 32767) & 64)) >> 5);
}
}
}
Duke.updatepindisplay(self.hitag, 0xffff);
}
}
class RedneckBowlingSectorLink : RedneckBowlingController
{ }
class RedneckBowlingBallSpot : RedneckBowlingController
{ }
class RedneckBowlingPinSpot : RedneckBowlingController
{ }

View file

@ -44,7 +44,10 @@ class DukeQueball : DukeActor
} }
else if (j == kHitSprite) else if (j == kHitSprite)
{ {
self.checkhitsprite(DukeActor(colli.hitactor())); // the logic here was inverted, so to set things right the type check had to be added.
let targ = DukeActor(colli.hitactor());
if (targ is 'DukeQueball')
targ.checkhitsprite(self);
} }
self.vel.X -= 1/16.; self.vel.X -= 1/16.;
@ -108,10 +111,10 @@ class DukeQueball : DukeActor
{ {
if (hitter is 'DukeQueball') if (hitter is 'DukeQueball')
{ {
hitter.vel.X = self.vel.X * 0.75; self.vel.X = hitter.vel.X * 0.75;
hitter.angle -= Normalize180(self.angle) * 2 + 180; self.angle -= Normalize180(hitter.angle) * 2 + 180;
self.angle = (self.pos.XY - hitter.pos.XY).Angle() - 90; hitter.angle = (hitter.pos.XY - self.pos.XY).Angle() - 90;
self.PlayActorSound("POOLBALLHIT"); hitter.PlayActorSound("POOLBALLHIT");
} }
else else
{ {

View file

@ -225,6 +225,7 @@ class DukeActor : CoreActor native
native int actorflag3(int mask); native int actorflag3(int mask);
native int attackerflag1(int mask); native int attackerflag1(int mask);
native int attackerflag2(int mask); native int attackerflag2(int mask);
deprecated("4.9") native bool checktype(String name); // this must not stay in the code, so mark it deprecated to keep the annoying warning at startup.
void commonEnemySetup(bool countkill = true) void commonEnemySetup(bool countkill = true)
@ -288,6 +289,14 @@ extend struct _
// On the script side we do not really want scattered global data that is publicly accessible. // On the script side we do not really want scattered global data that is publicly accessible.
struct DukeLevel struct DukeLevel
{ {
enum animtype_t
{
anim_floorz,
anim_ceilingz,
anim_vertexx,
anim_vertexy,
};
native DukeActor SpawnActor(sectortype sect, Vector3 pos, class<DukeActor> type, int shade, Vector2 scale, double angle, double vel, double zvel, DukeActor owner, int stat = -1); native DukeActor SpawnActor(sectortype sect, Vector3 pos, class<DukeActor> type, int shade, Vector2 scale, double angle, double vel, double zvel, DukeActor owner, int stat = -1);
native static int check_activator_motion(int lotag); native static int check_activator_motion(int lotag);
native static void operatemasterswitches(int lotag); native static void operatemasterswitches(int lotag);
@ -304,6 +313,8 @@ struct DukeLevel
native static void checkhitwall(walltype wal, DukeActor hitter, Vector3 hitpos); native static void checkhitwall(walltype wal, DukeActor hitter, Vector3 hitpos);
native static void checkhitceiling(sectortype wal, DukeActor hitter); native static void checkhitceiling(sectortype wal, DukeActor hitter);
native static DukeActor LocateTheLocator(int n, sectortype sect); native static DukeActor LocateTheLocator(int n, sectortype sect);
native static int getanimationindex(int type, sectortype sec);
native static int setanimation(sectortype animsect, int type, sectortype sec, double target, double vel);
} }
struct DukeStatIterator struct DukeStatIterator

View file

@ -153,6 +153,7 @@ struct Duke native
native static int global_random(); native static int global_random();
native static int GetSoundFlags(Sound snd); native static int GetSoundFlags(Sound snd);
native static int badguyID(int id); native static int badguyID(int id);
native static void updatepindisplay(int tag, int pinmask);
static int rnd(int val) static int rnd(int val)
{ {
return (random(0, 255) >= (255 - (val))); return (random(0, 255) >= (255 - (val)));

View file

@ -118,6 +118,22 @@ enum ESectorExBits
struct sectortype native struct sectortype native
{ {
enum EFindNextSector
{
Find_Floor = 0,
Find_Ceiling = 1,
Find_Down = 0,
Find_Up = 2,
Find_Safe = 4,
Find_CeilingUp = Find_Ceiling | Find_Up,
Find_CeilingDown = Find_Ceiling | Find_Down,
Find_FloorUp = Find_Floor | Find_Up,
Find_FloorDown = Find_Floor | Find_Down,
};
// panning byte fields were promoted to full floats to enable panning interpolation. // panning byte fields were promoted to full floats to enable panning interpolation.
native readonly float ceilingxpan; native readonly float ceilingxpan;
native readonly float ceilingypan; native readonly float ceilingypan;
@ -218,6 +234,8 @@ struct sectortype native
native int ceilingslope(); native int ceilingslope();
native int floorslope(); native int floorslope();
native double, double getslopes(Vector2 pos); native double, double getslopes(Vector2 pos);
native sectortype nextsectorneighborz(double refz, int find);
} }
//============================================================================= //=============================================================================