- DukeActor scriptification framework.

This commit is contained in:
Christoph Oelckers 2022-01-17 00:51:40 +01:00
parent 166235027c
commit c32a695384
17 changed files with 120 additions and 48 deletions

View file

@ -109,6 +109,7 @@ void PClassActor::StaticInit()
if (cls->IsDescendantOf(RUNTIME_CLASS(DCoreActor)))
{
AllActorClasses.Push(static_cast<PClassActor*>(cls));
static_cast<PClassActor*>(cls)->ActorInfo()->ResolveTextures(cls->TypeName.GetChars());
}
}
}
@ -228,3 +229,26 @@ PClassActor *PClassActor::GetReplacee()
return Replacee;
}
//==========================================================================
//
// This can only be done after all data has been set up.
//
//==========================================================================
void FActorInfo::ResolveTextures(const char* clsname)
{
SpriteSet.Resize(SpriteSetNames.Size());
for (unsigned i = 0; i < SpriteSet.Size(); i++)
{
SpriteSet[i] = TileFiles.tileForName(SpriteSetNames[i]);
if (SpriteSet[i] == -1) Printf("Unknown texture '%s' in sprite set for class %s\n", SpriteSetNames[i].GetChars(), clsname);
}
if (PicName.IsNotEmpty())
{
defsprite.picnum = TileFiles.tileForName(PicName);
if (defsprite.picnum == -1) Printf("Unknown texture '%s' in pic for class %s\n", PicName.GetChars(), clsname);
}
SpriteSetNames.Reset();
PicName = "";
}

View file

@ -45,8 +45,13 @@ struct FActorInfo
int DefaultCstat = 0;
spritetype defsprite{}; // Due to how the map format works we cannot define defaults for the sprite itself. These must be applied later.
// 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;
FActorInfo(const FActorInfo & other) = delete;
void ResolveTextures(const char* clsname);
};
// No objects of this type will be created ever - its only use is to static_cast

View file

@ -348,6 +348,35 @@ DCoreActor* InsertActor(PClass* type, sectortype* sector, int stat, bool tail)
assert(type->IsDescendantOf(RUNTIME_CLASS(DCoreActor)));
auto actor = static_cast<DCoreActor*>(type->CreateNew());
auto actorinfo = static_cast<PClassActor*>(actor->GetClass())->ActorInfo();
if (actorinfo)
{
actor->spr.cstat = (actor->spr.cstat & ~ESpriteFlags::FromInt(actorinfo->DefaultCstat)) | (actorinfo->defsprite.cstat & ESpriteFlags::FromInt(actorinfo->DefaultCstat));
#define setter(flag, var) if (actorinfo->DefaultFlags & flag) actor->spr.var = actorinfo->defsprite.var;
if (actorinfo->DefaultFlags & DEFF_STATNUM) stat = actorinfo->defsprite.statnum;
setter(DEFF_PICNUM, picnum);
setter(DEFF_ANG, angle);
setter(DEFF_XVEL, xint);
setter(DEFF_YVEL, yint);
setter(DEFF_ZVEL, inittype);
setter(DEFF_HITAG, hitag);
setter(DEFF_LOTAG, lotag);
setter(DEFF_EXTRA, extra);
setter(DEFF_DETAIL, detail);
setter(DEFF_SHADE, shade);
setter(DEFF_PAL, pal);
setter(DEFF_CLIPDIST, clipdist);
setter(DEFF_BLEND, blend);
setter(DEFF_XREPEAT, scale.X);
setter(DEFF_YREPEAT, scale.Y);
setter(DEFF_XOFFSET, xoffset);
setter(DEFF_YOFFSET, yoffset);
setter(DEFF_OWNER, intowner);
#undef setter
}
GC::WriteBarrier(actor);
InsertActorStat(actor, stat, tail);
@ -488,7 +517,7 @@ double DCoreActor::GetOffsetAndHeight(double& height)
return zofs - tileTopOffset(spr.picnum) * yscale;
}
DEFINE_FIELD_NAMED(DCoreActor, spr.sectp, sectp)
DEFINE_FIELD_NAMED(DCoreActor, spr.sectp, sector)
DEFINE_FIELD_NAMED(DCoreActor, spr.cstat, cstat)
DEFINE_FIELD_NAMED(DCoreActor, spr.cstat2, cstat2)
DEFINE_FIELD_NAMED(DCoreActor, spr.picnum, picnum)

View file

@ -1147,13 +1147,14 @@ int RunGame()
D_CheckNetGame();
UpdateGenericUI(ui_generic);
PClassActor::StaticInit();
MainLoop();
return 0; // this is never reached. MainLoop only exits via exception.
return 0;
}
//---------------------------------------------------------------------------
//
// The one and only main loop in the entire engine. Yay!
//
//
//---------------------------------------------------------------------------

View file

@ -313,11 +313,7 @@ static bool PointerCheck(PType *symtype, PType *checktype)
DEFINE_PROPERTY(pic, S, CoreActor)
{
PROP_STRING_PARM(str, 0);
bag.Info->ActorInfo()->defsprite.picnum = TileFiles.tileForName(str);
if (bag.Info->ActorInfo()->defsprite.picnum == -1)
{
I_Error("Unknown texture name '%s'", str);
}
bag.Info->ActorInfo()->PicName = str;
bag.Info->ActorInfo()->DefaultFlags |= DEFF_PICNUM;
}
@ -444,7 +440,7 @@ DEFINE_PROPERTY(clipdist, I, CoreActor)
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY(scalex, I, CoreActor)
DEFINE_PROPERTY(scalex, F, CoreActor)
{
PROP_INT_PARM(i, 0);
bag.Info->ActorInfo()->defsprite.scale.X = (i);
@ -454,7 +450,7 @@ DEFINE_PROPERTY(scalex, I, CoreActor)
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY(scaley, I, CoreActor)
DEFINE_PROPERTY(scaley, F, CoreActor)
{
PROP_INT_PARM(i, 0);
bag.Info->ActorInfo()->defsprite.scale.Y = (i);
@ -500,13 +496,7 @@ DEFINE_PROPERTY(spriteset, Ssssssssssssssssssss, CoreActor)
for (int i = 0; i < PROP_PARM_COUNT; ++i)
{
PROP_STRING_PARM(n, i);
int picnum = TileFiles.tileForName(n);
if (picnum == -1)
{
I_Error("Unknown texture name '%s'", n);
}
info->ActorInfo()->SpriteSet.Push(picnum);
info->ActorInfo()->SpriteSetNames.Push(n);
}
}

View file

@ -616,7 +616,6 @@ void movefx(void)
//---------------------------------------------------------------------------
//
// split out of movestandables
//
//---------------------------------------------------------------------------

View file

@ -1182,7 +1182,11 @@ void movestandables_d(void)
continue;
}
if (act->GetClass() != RUNTIME_CLASS(DDukeActor))
{
CallTick(act);
continue;
}
if (picnum >= CRANE && picnum <= CRANE +3)
{
movecrane(act, CRANE);

View file

@ -820,6 +820,11 @@ void movestandables_r(void)
continue;
}
if (act->GetClass() != RUNTIME_CLASS(DDukeActor))
{
CallTick(act);
continue;
}
if (picnum >= CRANE && picnum <= CRANE +3)
{
movecrane(act, CRANE);

View file

@ -402,7 +402,7 @@ void GameInterface::app_init()
void CallInitialize(DDukeActor* actor)
{
IFVIRTUALPTR(actor, DDukeActor, initialize)
IFVIRTUALPTR(actor, DDukeActor, Initialize)
{
VMValue val = actor;
VMCall(func, &val, 1, nullptr, 0);

View file

@ -967,7 +967,10 @@ static TArray<DDukeActor*> spawnactors(SpawnSpriteDef& sprites)
continue;
}
auto sprt = &sprites.sprites[i];
auto actor = static_cast<DDukeActor*>(InsertActor(RUNTIME_CLASS(DDukeActor), sprt->sectp, sprt->statnum));
auto info = spawnMap.CheckKey(sprt->picnum);
auto actor = static_cast<DDukeActor*>(InsertActor(info? info->Class() : RUNTIME_CLASS(DDukeActor), sprt->sectp, sprt->statnum));
if (actor)
{
spawns[j++] = actor;
actor->initFromSprite(&sprites.sprites[i]);
actor->time = i;
@ -975,6 +978,7 @@ static TArray<DDukeActor*> spawnactors(SpawnSpriteDef& sprites)
else actor->sprext = {};
actor->spsmooth = {};
}
}
leveltimer = sprites.sprites.Size();
return spawns;
}

View file

@ -56,12 +56,14 @@ DDukeActor* CreateActor(sectortype* whatsectp, const DVector3& pos, int s_pn, in
if (whatsectp == nullptr || !validSectorIndex(sectnum(whatsectp))) return nullptr;
// spawning out of range sprites will also crash.
if (s_pn < 0 || s_pn >= MAXTILES) return nullptr;
auto act = static_cast<DDukeActor*>(::InsertActor(RUNTIME_CLASS(DDukeActor), whatsectp, s_stat));
auto info = spawnMap.CheckKey(s_pn);
auto act = static_cast<DDukeActor*>(InsertActor(info ? info->Class() : RUNTIME_CLASS(DDukeActor), whatsectp, s_stat));
if (act == nullptr) return nullptr;
SetupGameVarsForActor(act);
act->basepicnum = info ? info->param : -1;
act->spr.pos = pos;
act->spr.picnum = s_pn;
act->spr.shade = s_shd;
@ -111,6 +113,13 @@ DDukeActor* CreateActor(sectortype* whatsectp, const DVector3& pos, int s_pn, in
return act;
}
DDukeActor* SpawnActor(sectortype* whatsectp, const DVector3& pos, int s_pn, int8_t s_shd, const DVector2& scale, DAngle s_ang, double s_vel, double s_zvel, DDukeActor* s_ow, int8_t s_stat)
{
auto actor = CreateActor(whatsectp, pos, s_pn, s_shd, scale, s_ang, s_vel, s_zvel, s_ow, s_stat);
if (actor) fi.spawninit(s_ow, actor, nullptr);
return actor;
}
//---------------------------------------------------------------------------
//

View file

@ -43,6 +43,11 @@ BEGIN_DUKE_NS
DDukeActor* spawninit_d(DDukeActor* actj, DDukeActor* act, TArray<DDukeActor*>* actors)
{
if (act->GetClass() != RUNTIME_CLASS(DDukeActor))
{
CallInitialize(act);
return act;
}
auto sectp = act->sector();
if (isWorldTour())

View file

@ -37,6 +37,11 @@ BEGIN_DUKE_NS
DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act, TArray<DDukeActor*>* actors)
{
if (act->GetClass() != RUNTIME_CLASS(DDukeActor))
{
CallInitialize(act);
return act;
}
auto sectp = act->sector();
switch (act->spr.picnum)

View file

@ -411,23 +411,4 @@ DEFINE_ACTION_FUNCTION_NATIVE(_DukePlayer, setpos, dukeplayer_setpos)
}
//---------------------------------------------------------------------------
//
// Class properties
//
//---------------------------------------------------------------------------
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY(spriteset, Ssssssssssssssssssss, DukeActor)
{
for (int i = 0; i < PROP_PARM_COUNT; ++i)
{
PROP_STRING_PARM(n, i);
bag.Info->ActorInfo()->SpriteSet.Push(TileFiles.tileForName(n));
}
}
END_DUKE_NS

View file

@ -0,0 +1,5 @@
spawnclasses
{
//1221 = DukeCranePole
//1222 = DukeCrane
}

View file

@ -0,0 +1,5 @@
spawnclasses
{
//1298 = DukeCranePole
//1299 = DukeCrane
}

View file

@ -50,6 +50,7 @@ version "4.9"
#include "zscript/games/duke/ui/screens.zs"
#include "zscript/games/duke/ui/cutscenes.zs"
#include "zscript/games/duke/ui/menu.zs"
#include "zscript/games/blood/bloodgame.zs"
#include "zscript/games/blood/ui/menu.zs"
#include "zscript/games/blood/ui/sbar.zs"