- implemented breakable walls with external definitions.

The scripted case does not work yet due to bad loading order of files.
This commit is contained in:
Christoph Oelckers 2022-12-04 09:18:57 +01:00
parent 8e17f1f0f5
commit c1a09196f0
13 changed files with 210 additions and 151 deletions

View file

@ -2351,6 +2351,47 @@ static void parseTileFlags(FScanner& sc, FScriptPosition& pos)
sc.SetCMode(false);
}
static void parseBreakWall(FScanner& sc, FScriptPosition& pos)
{
int basetile;
int breaktile;
FName sound;
VMFunction* handler = nullptr;
sc.SetCMode(true);
sc.MustGetString();
basetile = TileFiles.tileForName(sc.String);
sc.MustGetStringName(",");
sc.MustGetString();
breaktile = TileFiles.tileForName(sc.String);
sc.MustGetStringName(",");
sc.MustGetString();
sound = sc.String;
if (sc.CheckString(","))
{
sc.MustGetString();
size_t p = strcspn(sc.String, ".");
if (p == 0)
{
sc.ScriptMessage("Call to undefined function %s", sc.String);
return;
}
FString clsname(sc.String, p);
FString funcname = sc.String + p + 1;
handler = PClass::FindFunction(clsname, funcname);
if (handler == nullptr)
sc.ScriptMessage("Call to undefined function %s", sc.String);
// todo: validate the function's signature. Must be (walltype, TextureID, Sound, DukeActor)
}
breakWallMap.Insert(basetile, { breaktile, sound, handler });
sc.SetCMode(false);
}
//===========================================================================
//
//
@ -2445,6 +2486,7 @@ static const dispatch basetokens[] =
{ "spawnclasses", parseSpawnClasses },
{ "tileflag", parseTileFlags },
{ "breakwall", parseBreakWall },
{ nullptr, nullptr },
};

View file

@ -294,3 +294,12 @@ struct SpawnRec
};
using SpawnMap = TMap<int, SpawnRec>;
inline SpawnMap spawnMap;
struct BreakWallRec
{
int brokentex;
FName breaksound;
VMFunction* handler;
};
using BreakWallMap = TMap<int, BreakWallRec>;
inline BreakWallMap breakWallMap;

View file

@ -478,8 +478,9 @@ int sector_checktexture(sectortype* sec, int place, int intname)
if (!sec) ThrowAbortException(X_READ_NIL, nullptr);
int tilenum = TileFiles.tileForName(FName(ENamedName(intname)).GetChars());
return tilenum == place ? sec->ceilingpicnum : sec->floorpicnum;
return tilenum == (place == 0 ? sec->ceilingpicnum : sec->floorpicnum);
}
DEFINE_ACTION_FUNCTION_NATIVE(_sectortype, checktexture, sector_checktexture)
{
PARAM_SELF_STRUCT_PROLOGUE(sectortype);
@ -488,11 +489,26 @@ DEFINE_ACTION_FUNCTION_NATIVE(_sectortype, checktexture, sector_checktexture)
ACTION_RETURN_BOOL(sector_checktexture(self, place, name));
}
void sector_settexture(sectortype* sec, int place, int intname)
void sector_settexturename(sectortype* sec, int place, int intname)
{
if (!sec) ThrowAbortException(X_READ_NIL, nullptr);
int tilenum = TileFiles.tileForName(FName(ENamedName(intname)).GetChars());
(place ? sec->ceilingpicnum : sec->floorpicnum) = tilenum;
(place == 0 ? sec->ceilingpicnum : sec->floorpicnum) = tilenum;
}
DEFINE_ACTION_FUNCTION_NATIVE(_sectortype, settexturename, sector_settexturename)
{
PARAM_SELF_STRUCT_PROLOGUE(sectortype);
PARAM_INT(place);
PARAM_INT(name);
sector_settexturename(self, place, name);
return 0;
}
// This is declared as TextureID but for now receives a tilenum
void sector_settexture(sectortype* sec, int place, int tilenum)
{
if (!sec) ThrowAbortException(X_READ_NIL, nullptr);
(place == 0 ? sec->ceilingpicnum : sec->floorpicnum) = tilenum;
}
DEFINE_ACTION_FUNCTION_NATIVE(_sectortype, settexture, sector_settexture)
{
@ -701,6 +717,37 @@ DEFINE_ACTION_FUNCTION_NATIVE(_walltype, twosided, wall_twosided)
ACTION_RETURN_BOOL(self->twoSided());
}
void wall_settexturename(walltype* sec, int place, int intname)
{
if (!sec) ThrowAbortException(X_READ_NIL, nullptr);
int tilenum = TileFiles.tileForName(FName(ENamedName(intname)).GetChars());
(place ? sec->overpicnum : sec->picnum) = tilenum;
}
DEFINE_ACTION_FUNCTION_NATIVE(_walltype, settexturename, wall_settexturename)
{
PARAM_SELF_STRUCT_PROLOGUE(walltype);
PARAM_INT(place);
PARAM_INT(name);
wall_settexturename(self, place, name);
return 0;
}
// This is declared as TextureID but for now receives a tilenum
void wall_settexture(walltype* sec, int place, int tilenum)
{
if (!sec) ThrowAbortException(X_READ_NIL, nullptr);
(place ? sec->overpicnum : sec->picnum) = tilenum;
}
DEFINE_ACTION_FUNCTION_NATIVE(_walltype, settexture, wall_settexture)
{
PARAM_SELF_STRUCT_PROLOGUE(walltype);
PARAM_INT(place);
PARAM_INT(name);
wall_settexture(self, place, name);
return 0;
}
//=============================================================================
void tspritetype_setSpritePic(tspritetype* targ, DCoreActor* self, unsigned z)

View file

@ -538,4 +538,18 @@ void CallStandingOn(DDukeActor* actor, player_struct* p)
}
CCMD(changewalltexture)
{
if (argv.argc() < 2) return;
int tile = TileFiles.tileForName(argv[1]);
if (tile < 0) tile = (int)strtol(argv[1], nullptr, 10);
HitInfoBase hit;
hitscan(ps[0].actor->spr.pos, ps[0].cursector, DVector3(ps[0].actor->spr.Angles.Yaw.ToVector(), 0) * 1024, hit, CLIPMASK1);
if (hit.hitWall)
{
hit.hitWall->picnum = tile;
}
}
END_DUKE_NS

View file

@ -316,7 +316,7 @@ static void shootweapon(DDukeActor* actor, int p, DVector3 pos, DAngle ang, int
if (hit.actor())
{
if (hit.actor()->spr.picnum == 1930)
if (hit.actor()->spr.picnum == TORNADO)
return;
fi.checkhitsprite(hit.actor(), spark);
if (hit.actor()->isPlayer() && (ud.coop != 1 || ud.ffire == 1))
@ -459,7 +459,7 @@ static void shootstuff(DDukeActor* actor, int p, DVector3 pos, DAngle ang, int a
scount = 1;
if (atwith == SHITBALL)
{
if (actor->spr.picnum == 8705)
if (actor->spr.picnum == MAMA)
vel = 37.5;
else
vel = 25;
@ -476,7 +476,7 @@ static void shootstuff(DDukeActor* actor, int p, DVector3 pos, DAngle ang, int a
{
vel = 52.5;
pos.Z -= 4;
if (actor->spr.picnum == 4649)
if (actor->spr.picnum == HULK)
{
pos += (actor->spr.Angles.Yaw + DAngle45).ToVector() * 16;
pos.Z += 12;

View file

@ -33,6 +33,7 @@ Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms
#include "mapinfo.h"
#include "dukeactor.h"
#include "secrets.h"
#include "vm.h"
// PRIMITIVE
BEGIN_DUKE_NS
@ -869,7 +870,21 @@ void checkhitwall_r(DDukeActor* spr, walltype* wal, const DVector3& pos, int atw
}
}
switch (wal->picnum)
auto data = breakWallMap.CheckKey(wal->picnum);
if (data)
{
if (!data->handler)
{
wal->picnum = data->brokentex;
S_PlayActorSound(S_FindSound(data->breaksound.GetChars()), spr);
}
else
{
VMValue args[4] = { wal, data->brokentex, S_FindSound(data->breaksound.GetChars()).index(), spr };
VMCall(data->handler, args, 4, nullptr, 0);
}
}
else switch (wal->picnum)
{
case IRONWHEELSWITCH:
if (isRRRA()) break;
@ -901,139 +916,6 @@ void checkhitwall_r(DDukeActor* spr, walltype* wal, const DVector3& pos, int atw
}
return;
}
case RRTILE7555:
if (!isRRRA()) break;
wal->picnum = RRTILE5015;
S_PlayActorSound(GLASS_HEAVYBREAK, spr);
return;
case RRTILE7441:
if (!isRRRA()) break;
wal->picnum = RRTILE5016;
S_PlayActorSound(GLASS_HEAVYBREAK, spr);
return;
case RRTILE7559:
if (!isRRRA()) break;
wal->picnum = RRTILE5017;
S_PlayActorSound(GLASS_HEAVYBREAK, spr);
return;
case RRTILE7433:
if (!isRRRA()) break;
wal->picnum = RRTILE5018;
S_PlayActorSound(GLASS_HEAVYBREAK, spr);
return;
case RRTILE7557:
if (!isRRRA()) break;
wal->picnum = RRTILE5019;
S_PlayActorSound(GLASS_HEAVYBREAK, spr);
return;
case RRTILE7553:
if (!isRRRA()) break;
wal->picnum = RRTILE5020;
S_PlayActorSound(GLASS_HEAVYBREAK, spr);
return;
case RRTILE7552:
if (!isRRRA()) break;
wal->picnum = RRTILE5021;
S_PlayActorSound(GLASS_HEAVYBREAK, spr);
return;
case RRTILE7568:
if (!isRRRA()) break;
wal->picnum = RRTILE5022;
S_PlayActorSound(GLASS_HEAVYBREAK, spr);
return;
case RRTILE7540:
if (!isRRRA()) break;
wal->picnum = RRTILE5023;
S_PlayActorSound(GLASS_HEAVYBREAK, spr);
return;
case RRTILE7558:
if (!isRRRA()) break;
wal->picnum = RRTILE5024;
S_PlayActorSound(GLASS_HEAVYBREAK, spr);
return;
case RRTILE7554:
if (!isRRRA()) break;
wal->picnum = RRTILE5025;
S_PlayActorSound(GLASS_HEAVYBREAK, spr);
return;
case RRTILE7579:
if (!isRRRA()) break;
wal->picnum = RRTILE5026;
S_PlayActorSound(GLASS_HEAVYBREAK, spr);
return;
case RRTILE7561:
if (!isRRRA()) break;
wal->picnum = RRTILE5027;
S_PlayActorSound(GLASS_HEAVYBREAK, spr);
return;
case RRTILE7580:
if (!isRRRA()) break;
wal->picnum = RRTILE5037;
S_PlayActorSound(GLASS_HEAVYBREAK, spr);
return;
case RRTILE8227:
if (!isRRRA()) break;
wal->picnum = RRTILE5070;
S_PlayActorSound(GLASS_HEAVYBREAK, spr);
return;
case RRTILE8503:
if (!isRRRA()) break;
wal->picnum = RRTILE5079;
S_PlayActorSound(GLASS_HEAVYBREAK, spr);
return;
case RRTILE8567:
case RRTILE8568:
case RRTILE8569:
case RRTILE8570:
case RRTILE8571:
if (!isRRRA()) break;
wal->picnum = RRTILE5082;
S_PlayActorSound(GLASS_HEAVYBREAK, spr);
return;
case RRTILE7859:
if (!isRRRA()) break;
wal->picnum = RRTILE5081;
S_PlayActorSound(GLASS_HEAVYBREAK, spr);
return;
case RRTILE8496:
if (!isRRRA()) break;
wal->picnum = RRTILE5061;
S_PlayActorSound(GLASS_HEAVYBREAK, spr);
return;
case RRTILE8617:
if (!isRRRA()) break;
if (numplayers < 2)
{
wal->picnum = RRTILE8618;
S_PlayActorSound(47, spr);
}
return;
case RRTILE8620:
if (!isRRRA()) break;
wal->picnum = RRTILE8621;
S_PlayActorSound(47, spr);
return;
case RRTILE8622:
if (!isRRRA()) break;
wal->picnum = RRTILE8623;
S_PlayActorSound(495, spr);
return;
case WEAPONCABINET:
if (!isRRRA()) break;
wal->picnum = WEAPONCABINETBROKE;
S_PlayActorSound(GLASS_HEAVYBREAK, spr);
return;
case RRTILE8497:
if (!isRRRA()) break;
wal->picnum = RRTILE5076;
S_PlayActorSound(495, spr);
return;
case RRTILE7533:
if (!isRRRA()) break;
wal->picnum = RRTILE5035;
S_PlayActorSound(495, spr);
return;
case COLAMACHINE:
case VENDMACHINE:
breakwall(wal->picnum + 2, spr, wal);

View file

@ -486,29 +486,31 @@ DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, spawnweaponorammo, DukeActor_spawnweap
ACTION_RETURN_POINTER(DukeActor_spawnweaponorammo(self, type));
}
void DukeActor_Lotsofglass(DDukeActor* origin, int count)
void DukeActor_Lotsofglass(DDukeActor* origin, int count, walltype* wal)
{
lotsofglass(origin, nullptr, count);
lotsofglass(origin, wal, count);
}
DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, lotsofglass, DukeActor_Lotsofglass)
{
PARAM_SELF_PROLOGUE(DDukeActor);
PARAM_INT(count);
DukeActor_Lotsofglass(self, count);
PARAM_POINTER(wall, walltype);
DukeActor_Lotsofglass(self, count, wall);
return 0;
}
void DukeActor_Lotsofcolourglass(DDukeActor* origin, int count)
void DukeActor_Lotsofcolourglass(DDukeActor* origin, int count, walltype* wal)
{
lotsofcolourglass(origin, nullptr, count);
lotsofcolourglass(origin, wal, count);
}
DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, lotsofcolourglass, DukeActor_Lotsofcolourglass)
{
PARAM_SELF_PROLOGUE(DDukeActor);
PARAM_INT(count);
DukeActor_Lotsofcolourglass(self, count);
PARAM_POINTER(wall, walltype);
DukeActor_Lotsofcolourglass(self, count, wall);
return 0;
}

View file

@ -193,4 +193,35 @@ tileflag TFLAG_BLOCKDOOR {
RRTILE8565
RRTILE8605
}
breakwall RRTILE7555, RRTILE5015, GLASS_HEAVYBREAK
breakwall RRTILE7441, RRTILE5016, GLASS_HEAVYBREAK
breakwall RRTILE7559, RRTILE5017, GLASS_HEAVYBREAK
breakwall RRTILE7433, RRTILE5018, GLASS_HEAVYBREAK
breakwall RRTILE7557, RRTILE5019, GLASS_HEAVYBREAK
breakwall RRTILE7553, RRTILE5020, GLASS_HEAVYBREAK
breakwall RRTILE7552, RRTILE5021, GLASS_HEAVYBREAK
breakwall RRTILE7568, RRTILE5022, GLASS_HEAVYBREAK
breakwall RRTILE7540, RRTILE5023, GLASS_HEAVYBREAK
breakwall RRTILE7558, RRTILE5024, GLASS_HEAVYBREAK
breakwall RRTILE7554, RRTILE5025, GLASS_HEAVYBREAK
breakwall RRTILE7579, RRTILE5026, GLASS_HEAVYBREAK
breakwall RRTILE7561, RRTILE5027, GLASS_HEAVYBREAK
breakwall RRTILE7580, RRTILE5037, GLASS_HEAVYBREAK
breakwall RRTILE8227, RRTILE5070, GLASS_HEAVYBREAK
breakwall RRTILE8503, RRTILE5079, GLASS_HEAVYBREAK
breakwall RRTILE8567, RRTILE5082, GLASS_HEAVYBREAK
breakwall RRTILE8568, RRTILE5082, GLASS_HEAVYBREAK
breakwall RRTILE8569, RRTILE5082, GLASS_HEAVYBREAK
breakwall RRTILE8570, RRTILE5082, GLASS_HEAVYBREAK
breakwall RRTILE8571, RRTILE5082, GLASS_HEAVYBREAK
breakwall RRTILE7859, RRTILE5081, GLASS_HEAVYBREAK
breakwall RRTILE8496, RRTILE5061, GLASS_HEAVYBREAK
breakwall RRTILE8620, RRTILE8621, WOODBREK
breakwall RRTILE8622, RRTILE8623, SIGNHIT
breakwall WEAPONCABINET, WEAPONCABINETBROKE, GLASS_HEAVYBREAK
breakwall RRTILE8497, RRTILE5076, SIGNHIT
breakwall RRTILE7533, RRTILE5035, SIGNHIT
breakwall RRTILE8617, RRTILE8618, WOODBREK, "RedneckBreakwalls.SinglePlayerBreak"

View file

@ -115,6 +115,8 @@ version "4.10"
#include "zscript/games/duke/actors/airplane.zs"
#include "zscript/games/duke/actors/piano.zs"
#include "zscript/games/duke/world/redneckbreak.zs"
#include "zscript/games/blood/bloodgame.zs"
#include "zscript/games/blood/ui/menu.zs"
#include "zscript/games/blood/ui/sbar.zs"

View file

@ -129,7 +129,7 @@ class DukeFanSprite : DukeActor
self.setSpriteSetImage(1);
self.cstat &= ~CSTAT_SPRITE_BLOCK_ALL;
if (self.sector.CheckTexture(sectortype.floor, "FANSHADOW"))
self.sector.SetTexture(sectortype.floor, "FANSHADOWBROKE");
self.sector.SetTextureName(sectortype.floor, "FANSHADOWBROKE");
self.PlayActorSound("GLASS_HEAVYBREAK");
for (int j = 0; j < 16; j++) self.RANDOMSCRAP();

View file

@ -171,8 +171,8 @@ class DukeActor : CoreActor native
native DukeActor spawn(Name type);
native DukeActor spawnsprite(int type); // for cases where the map has a picnum stored. Avoid when possible.
native DukeActor spawnweaponorammo(int type);
native void lotsofglass(int count);
native void lotsofcolourglass(int count);
native void lotsofglass(int count, walltype wal = null);
native void lotsofcolourglass(int count, walltype wal = null);
native void makeitfall();
native void detonate(name type);
native void checkhitdefault(DukeActor proj);

View file

@ -0,0 +1,22 @@
// Container for handler functions that handle walls with breakable textures
struct RedneckBreakWalls
{
static void breakwall(TextureID newpn, DukeActor spr, walltype wal)
{
wal.SetTexture(walltype.main, newpn);
spr.PlayActorSound("VENT_BUST");
spr.PlayActorSound("GLASS_HEAVYBREAK");
spr.lotsofglass(10, wal);
}
static void SinglePlayerBreak(walltype wal, TextureID newtex, Sound snd, DukeActor hitter)
{
if (ud.multimode < 2)
{
wal.SetTexture(walltype.main, newtex);
hitter.PlayActorSound(snd);
}
}
}

View file

@ -241,7 +241,8 @@ struct sectortype native
native double, double getslopes(Vector2 pos);
native sectortype nextsectorneighborz(double refz, int find);
native bool CheckTexture(int place, Name tex);
native void SetTexture(int place, Name tex);
native void SetTextureName(int place, Name tex);
native void SetTexture(int place, TextureID tex);
}
@ -253,6 +254,11 @@ struct sectortype native
struct walltype native
{
enum EPlane
{
main = 0,
over = 1,
}
native readonly Vector2 pos;
native readonly int point2;
@ -296,6 +302,8 @@ struct walltype native
native double Length();
native void move(Vector2 vec);
native void dragpoint(Vector2 vec);
native void SetTextureName(int place, Name tex);
native void SetTexture(int place, TextureID tex);
}
//=============================================================================