From 3aafcb94f168a1a900024d5489eaf449dc22b901 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 1 Oct 2023 20:39:40 +0200 Subject: [PATCH] exported XSECTOR and XWALL. this required an extension to the ZScript front end to allow defining the bitfield flag variables which cannot have their address taken. --- source/CMakeLists.txt | 1 + .../common/scripting/frontend/zcc-parse.lemon | 10 + .../common/scripting/frontend/zcc_compile.cpp | 5 + .../common/scripting/frontend/zcc_compile.h | 1 + source/core/zcc_compile_raze.cpp | 199 +++++++++++++++--- source/core/zcc_compile_raze.h | 1 + source/games/blood/src/actor.cpp | 2 +- source/games/blood/src/ai.cpp | 4 +- source/games/blood/src/aiunicult.cpp | 4 +- source/games/blood/src/db.cpp | 10 +- source/games/blood/src/loadsave.cpp | 9 +- source/games/blood/src/mapstructs.h | 23 +- source/games/blood/src/nnexts.cpp | 60 +++--- source/games/blood/src/nnsprinsect.cpp | 2 +- source/games/blood/src/triggers.cpp | 4 +- source/games/blood/src/vmexports.cpp | 57 ++++- wadsrc/static/zscript/games/maptypes.zs | 128 ++++++++++- 17 files changed, 432 insertions(+), 88 deletions(-) diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index d4f43807e..58df56438 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -699,6 +699,7 @@ set( NOT_COMPILED_SOURCE_FILES games/blood/src/view.cpp games/blood/src/warp.cpp games/blood/src/weapon.cpp + games/blood/src/vmexports.cpp # Duke games/duke/src/actors.cpp diff --git a/source/common/scripting/frontend/zcc-parse.lemon b/source/common/scripting/frontend/zcc-parse.lemon index 71385c582..fb84d279c 100644 --- a/source/common/scripting/frontend/zcc-parse.lemon +++ b/source/common/scripting/frontend/zcc-parse.lemon @@ -374,6 +374,15 @@ flag_def(X) ::= FLAGDEF(T) IDENTIFIER(A) COLON IDENTIFIER(B) COMMA INTCONST(C) S X = def; } +flag_def(X) ::= FLAGDEF(T) INTERNAL IDENTIFIER(A) COLON IDENTIFIER(B) COMMA INTCONST(C) SEMICOLON. +{ + NEW_AST_NODE(FlagDef,def,T); + def->NodeName = A.Name(); + def->RefName = B.Name(); + def->BitValue = C.Int | 0x10000; + X = def; +} + identifier_list(X) ::= IDENTIFIER(A). { @@ -433,6 +442,7 @@ struct_member(X) ::= declarator(A). { X = A; /*X-overwrites-A*/ } struct_member(X) ::= enum_def(A). { X = A; /*X-overwrites-A*/ } struct_member(X) ::= const_def(A). { X = A; /*X-overwrites-A*/ } struct_member(X) ::= staticarray_statement(A). { X = A; /*X-overwrites-A*/ } +struct_member(X) ::= flag_def(A). { X = A; /*X-overwrites-A*/ } /*----- Constant Definition ------*/ /* Like UnrealScript, a constant's type is implied by its value's type. */ diff --git a/source/common/scripting/frontend/zcc_compile.cpp b/source/common/scripting/frontend/zcc_compile.cpp index fb21526f1..fd4572a44 100644 --- a/source/common/scripting/frontend/zcc_compile.cpp +++ b/source/common/scripting/frontend/zcc_compile.cpp @@ -452,6 +452,11 @@ void ZCCCompiler::ProcessStruct(ZCC_Struct *cnode, PSymbolTreeNode *treenode, ZC } break; + case AST_FlagDef: + cls->FlagDefs.Push(static_cast(node)); + break; + + default: assert(0 && "Unhandled AST node type"); break; diff --git a/source/common/scripting/frontend/zcc_compile.h b/source/common/scripting/frontend/zcc_compile.h index b6f32018d..82c6342ff 100644 --- a/source/common/scripting/frontend/zcc_compile.h +++ b/source/common/scripting/frontend/zcc_compile.h @@ -23,6 +23,7 @@ struct ZCC_StructWork TArray Fields; TArray Functions; TArray Arrays; + TArray FlagDefs; ZCC_StructWork() { diff --git a/source/core/zcc_compile_raze.cpp b/source/core/zcc_compile_raze.cpp index 1e8406ae1..c98919d0e 100644 --- a/source/core/zcc_compile_raze.cpp +++ b/source/core/zcc_compile_raze.cpp @@ -89,6 +89,11 @@ void ZCCRazeCompiler::CompileAllProperties() if (c->FlagDefs.Size() > 0) CompileFlagDefs(c->ClassType(), c->FlagDefs, c->Type()->TypeName); + } + for (auto s : Structs) + { + if (s->FlagDefs.Size() > 0) + CompileFlagDefs(s->Type(), s->FlagDefs, s->Type()->TypeName); } } @@ -158,17 +163,22 @@ bool ZCCRazeCompiler::CompileProperties(PClass *type, TArray &Pr bool ZCCRazeCompiler::CompileFlagDefs(PClass *type, TArray &Properties, FName prefix) { - if (!type->IsDescendantOf(RUNTIME_CLASS(DCoreActor))) - { - Error(Properties[0], "Flags can only be defined for actors"); - return false; - } for (auto p : Properties) { - PField *field; - FName referenced = FName(p->RefName); + bool internal = (p->BitValue & 0x10000); // defines just a variable for the flag but no property. + if (!internal) + { + if (!type->IsDescendantOf(RUNTIME_CLASS(DCoreActor))) + { + Error(Properties[0], "Flag properties can only be defined for actors"); + return false; + } + } + FName referenced(p->RefName); - if (FName(p->NodeName) == FName("prefix") && fileSystem.GetFileContainer(Lump) == 0) + PField *field; + + if (!internal && FName(p->NodeName) == FName("prefix") && fileSystem.GetFileContainer(Lump) == 0) { // only for internal definitions: Allow setting a prefix. This is only for compatiblity with the old DECORATE property parser, but not for general use. prefix = referenced; @@ -190,32 +200,72 @@ bool ZCCRazeCompiler::CompileFlagDefs(PClass *type, TArray &Prope else field = nullptr; - FString qualifiedname; - // Store the full qualified name and prepend some 'garbage' to the name so that no conflicts with other symbol types can happen. - // All these will be removed from the symbol table after the compiler finishes to free up the allocated space. - FName name = FName(p->NodeName); - for (int i = 0; i < 2; i++) + FName name(p->NodeName); + if (!internal) { - if (i == 0) qualifiedname.Format("@flagdef@%s", name.GetChars()); - else + FString qualifiedname; + // Store the full qualified name and prepend some 'garbage' to the name so that no conflicts with other symbol types can happen. + // All these will be removed from the symbol table after the compiler finishes to free up the allocated space. + for (int i = 0; i < 2; i++) { - if (prefix == NAME_None) continue; - qualifiedname.Format("@flagdef@%s.%s", prefix.GetChars(), name.GetChars()); - } + if (i == 0) qualifiedname.Format("@flagdef@%s", name.GetChars()); + else + { + if (prefix == NAME_None) continue; + qualifiedname.Format("@flagdef@%s.%s", prefix.GetChars(), name.GetChars()); + } - if (!type->VMType->Symbols.AddSymbol(Create(qualifiedname, field, p->BitValue, i == 0 && prefix != NAME_None))) - { - Error(p, "Unable to add flag definition %s to class %s", FName(p->NodeName).GetChars(), type->TypeName.GetChars()); + if (!type->VMType->Symbols.AddSymbol(Create(qualifiedname, field, p->BitValue, i == 0 && prefix != NAME_None))) + { + Error(p, "Unable to add flag definition %s to class %s", FName(p->NodeName).GetChars(), type->TypeName.GetChars()); + } } + if (field != nullptr) + type->VMType->AddNativeField(FStringf("b%s", name.GetChars()), TypeSInt32, field->Offset, 0, 1 << p->BitValue); + } - - if (field != nullptr) - type->VMType->AddNativeField(FStringf("b%s", name.GetChars()), TypeSInt32, field->Offset, 0, 1 << p->BitValue); + // internal ones get no 'b'. + else if (field != nullptr) + type->VMType->AddNativeField(name.GetChars(), TypeSInt32, field->Offset, 0, 1 << p->BitValue); } } return true; } +bool ZCCRazeCompiler::CompileFlagDefs(PContainerType* type, TArray& Properties, FName prefix) +{ + for (auto p : Properties) + { + bool internal = (p->BitValue & 0x10000); // defines just a variable for the flag but no property. + if (!internal) + { + Error(Properties[0], "Flag properties can only be defined for actors"); + return false; + } + FName referenced(p->RefName); + + PField* field; + + if (referenced != NAME_None) + { + field = dyn_cast(type->Symbols.FindSymbol(referenced, true)); + if (field == nullptr) + { + Error(p, "Variable %s not found in %s", referenced.GetChars(), type->TypeName.GetChars()); + } + else if (!field->Type->isInt() || field->Type->Size != 4) + { + Error(p, "Variable %s in %s must have a size of 4 bytes for use as flag storage", referenced.GetChars(), type->TypeName.GetChars()); + } + + FName name(p->NodeName); + type->AddNativeField(name.GetChars(), TypeSInt32, field->Offset, 0, 1 << (p->BitValue & 0xffff)); + return true; + } + } + return false; +} + //========================================================================== // // Parses an actor property's parameters and calls the handler @@ -449,9 +499,105 @@ void ZCCRazeCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt * } else if (!ex->isConstant()) { + if (ex->ExprType == EFX_VectorValue && ex->ValueType == f->Type) + { + auto v = static_cast(ex); + if (f->Type == TypeVector2) + { + if(!v->isConstVector(2)) + { + Error(exp, "%s: non-constant Vector2 parameter", prop->SymbolName.GetChars()); + return; + } + (*(DVector2*)addr) = DVector2( + static_cast(v->xyzw[0])->GetValue().GetFloat(), + static_cast(v->xyzw[1])->GetValue().GetFloat() + ); + goto vector_ok; + } + else if (f->Type == TypeFVector2) + { + if(!v->isConstVector(2)) + { + Error(exp, "%s: non-constant FVector2 parameter", prop->SymbolName.GetChars()); + return; + } + (*(FVector2*)addr) = FVector2( + float(static_cast(v->xyzw[0])->GetValue().GetFloat()), + float(static_cast(v->xyzw[1])->GetValue().GetFloat()) + ); + goto vector_ok; + } + else if (f->Type == TypeVector3) + { + if(!v->isConstVector(3)) + { + Error(exp, "%s: non-constant Vector3 parameter", prop->SymbolName.GetChars()); + return; + } + (*(DVector3*)addr) = DVector3( + static_cast(v->xyzw[0])->GetValue().GetFloat(), + static_cast(v->xyzw[1])->GetValue().GetFloat(), + static_cast(v->xyzw[2])->GetValue().GetFloat() + ); + goto vector_ok; + } + else if (f->Type == TypeFVector3) + { + if(!v->isConstVector(3)) + { + Error(exp, "%s: non-constant FVector3 parameter", prop->SymbolName.GetChars()); + return; + } + (*(FVector3*)addr) = FVector3( + float(static_cast(v->xyzw[0])->GetValue().GetFloat()), + float(static_cast(v->xyzw[1])->GetValue().GetFloat()), + float(static_cast(v->xyzw[2])->GetValue().GetFloat()) + ); + goto vector_ok; + } + else if (f->Type == TypeVector4) + { + if(!v->isConstVector(4)) + { + Error(exp, "%s: non-constant Vector4 parameter", prop->SymbolName.GetChars()); + return; + } + (*(DVector4*)addr) = DVector4( + static_cast(v->xyzw[0])->GetValue().GetFloat(), + static_cast(v->xyzw[1])->GetValue().GetFloat(), + static_cast(v->xyzw[2])->GetValue().GetFloat(), + static_cast(v->xyzw[3])->GetValue().GetFloat() + ); + goto vector_ok; + } + else if (f->Type == TypeFVector4) + { + if(!v->isConstVector(4)) + { + Error(exp, "%s: non-constant FVector4 parameter", prop->SymbolName.GetChars()); + return; + } + (*(FVector4*)addr) = FVector4( + float(static_cast(v->xyzw[0])->GetValue().GetFloat()), + float(static_cast(v->xyzw[1])->GetValue().GetFloat()), + float(static_cast(v->xyzw[2])->GetValue().GetFloat()), + float(static_cast(v->xyzw[3])->GetValue().GetFloat()) + ); + goto vector_ok; + } + else + { + Error(exp, "%s: invalid vector parameter", prop->SymbolName.GetChars()); + return; + } + } + else + { + if (exp->Type != TypeError) Error(exp, "%s: non-constant parameter", prop->SymbolName.GetChars()); + return; + } // If we get TypeError, there has already been a message from deeper down so do not print another one. - if (exp->Type != TypeError) Error(exp, "%s: non-constant parameter", prop->SymbolName.GetChars()); - return; } if (f->Type == TypeBool) @@ -508,6 +654,7 @@ void ZCCRazeCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt * { Error(property, "unhandled property type %s", f->Type->DescriptiveName()); } +vector_ok: exp->ToErrorNode(); // invalidate after processing. exp = static_cast(exp->SiblingNext); } diff --git a/source/core/zcc_compile_raze.h b/source/core/zcc_compile_raze.h index b088ec577..8ddf0e12a 100644 --- a/source/core/zcc_compile_raze.h +++ b/source/core/zcc_compile_raze.h @@ -18,6 +18,7 @@ private: void CompileAllProperties(); bool CompileProperties(PClass *type, TArray &Properties, FName prefix); bool CompileFlagDefs(PClass *type, TArray &Properties, FName prefix); + bool CompileFlagDefs(PContainerType* type, TArray& Properties, FName prefix); void DispatchProperty(FPropertyInfo *prop, ZCC_PropertyStmt *property, DCoreActor *defaults, Baggage &bag); void DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *property, DCoreActor *defaults, Baggage &bag); void ProcessDefaultProperty(PClassActor *cls, ZCC_PropertyStmt *prop, Baggage &bag); diff --git a/source/games/blood/src/actor.cpp b/source/games/blood/src/actor.cpp index eb37ffbce..122631263 100644 --- a/source/games/blood/src/actor.cpp +++ b/source/games/blood/src/actor.cpp @@ -6225,7 +6225,7 @@ DBloodActor* actSpawnDude(DBloodActor* source, int nType, double dist) spawned->xspr.dudeGuard = source->xspr.dudeGuard; spawned->xspr.dudeAmbush = source->xspr.dudeAmbush; spawned->xspr.dudeFlag4 = source->xspr.dudeFlag4; - spawned->xspr.unused1 = source->xspr.unused1; + spawned->xspr.modernFlags = source->xspr.modernFlags; break; } } diff --git a/source/games/blood/src/ai.cpp b/source/games/blood/src/ai.cpp index 49a4ad3c7..400470706 100644 --- a/source/games/blood/src/ai.cpp +++ b/source/games/blood/src/ai.cpp @@ -1924,12 +1924,12 @@ void aiInitSprite(DBloodActor* actor) if (stateTimer > 0) { if (uwater) aiPatrolState(actor, kAiStatePatrolWaitW); - else if (actor->xspr.unused1 & kDudeFlagCrouch) aiPatrolState(actor, kAiStatePatrolWaitC); + else if (actor->xspr.modernFlags & kDudeFlagCrouch) aiPatrolState(actor, kAiStatePatrolWaitC); else aiPatrolState(actor, kAiStatePatrolWaitL); actor->xspr.stateTimer = stateTimer; // restore state timer } else if (uwater) aiPatrolState(actor, kAiStatePatrolMoveW); - else if (actor->xspr.unused1 & kDudeFlagCrouch) aiPatrolState(actor, kAiStatePatrolMoveC); + else if (actor->xspr.modernFlags & kDudeFlagCrouch) aiPatrolState(actor, kAiStatePatrolMoveC); else aiPatrolState(actor, kAiStatePatrolMoveL); } } diff --git a/source/games/blood/src/aiunicult.cpp b/source/games/blood/src/aiunicult.cpp index f14508988..0d42ddf8b 100644 --- a/source/games/blood/src/aiunicult.cpp +++ b/source/games/blood/src/aiunicult.cpp @@ -1907,7 +1907,7 @@ DBloodActor* genDudeSpawn(DBloodActor* source, DBloodActor* actor, double nDist) spawned->xspr.dudeGuard = source->xspr.dudeGuard; spawned->xspr.dudeAmbush = source->xspr.dudeAmbush; spawned->xspr.dudeFlag4 = source->xspr.dudeFlag4; - spawned->xspr.unused1 = source->xspr.unused1; + spawned->xspr.modernFlags = source->xspr.modernFlags; break; } } @@ -1986,7 +1986,7 @@ void genDudeTransform(DBloodActor* actor) actor->xspr.dudeDeaf = actIncarnation->xspr.dudeDeaf; actor->xspr.dudeAmbush = actIncarnation->xspr.dudeAmbush; actor->xspr.dudeFlag4 = actIncarnation->xspr.dudeFlag4; - actor->xspr.unused1 = actIncarnation->xspr.unused1; + actor->xspr.modernFlags = actIncarnation->xspr.modernFlags; actor->xspr.dropMsg = actIncarnation->xspr.dropMsg; actor->xspr.key = actIncarnation->xspr.key; diff --git a/source/games/blood/src/db.cpp b/source/games/blood/src/db.cpp index e121a6e2c..1510a8ffc 100644 --- a/source/games/blood/src/db.cpp +++ b/source/games/blood/src/db.cpp @@ -341,7 +341,7 @@ void dbLoadMap(const char* pPath, DVector3& pos, short* pAngle, sectortype** cur pXSector->Depth = bitReader.readUnsigned(3); pXSector->panVel = bitReader.readUnsigned(8); pXSector->panAngle = mapangle(bitReader.readUnsigned(11)); - pXSector->unused1 = bitReader.readUnsigned(1); + pXSector->pauseMotion = bitReader.readUnsigned(1); pXSector->decoupled = bitReader.readUnsigned(1); pXSector->triggerOnce = bitReader.readUnsigned(1); pXSector->isTriggered = bitReader.readUnsigned(1); @@ -535,9 +535,9 @@ void dbLoadMap(const char* pPath, DVector3& pos, short* pAngle, sectortype** cur pXSprite->waitTime = bitReader.readUnsigned(12); pXSprite->restState = bitReader.readUnsigned(1); pXSprite->Interrutable = bitReader.readUnsigned(1); - pXSprite->unused1 = bitReader.readUnsigned(2); + pXSprite->modernFlags = bitReader.readUnsigned(2); pXSprite->respawnPending = bitReader.readUnsigned(2); - pXSprite->unused2 = bitReader.readUnsigned(1); + pXSprite->patrolstate = bitReader.readUnsigned(1); pXSprite->lT = bitReader.readUnsigned(1); pXSprite->dropMsg = bitReader.readUnsigned(8); pXSprite->Decoupled = bitReader.readUnsigned(1); @@ -551,7 +551,7 @@ void dbLoadMap(const char* pPath, DVector3& pos, short* pAngle, sectortype** cur pXSprite->Touch = bitReader.readUnsigned(1); pXSprite->Sight = bitReader.readUnsigned(1); pXSprite->Proximity = bitReader.readUnsigned(1); - pXSprite->unused3 = bitReader.readUnsigned(2); + pXSprite->sightstuff = bitReader.readUnsigned(2); pXSprite->lSkill = bitReader.readUnsigned(5); pXSprite->lS = bitReader.readUnsigned(1); pXSprite->lB = bitReader.readUnsigned(1); @@ -566,7 +566,7 @@ void dbLoadMap(const char* pPath, DVector3& pos, short* pAngle, sectortype** cur pXSprite->medium = bitReader.readUnsigned(2); pXSprite->respawn = bitReader.readUnsigned(2); pXSprite->data4 = bitReader.readUnsigned(16); - pXSprite->unused4 = bitReader.readUnsigned(6); + pXSprite->patrolturndelay = bitReader.readUnsigned(6); pXSprite->lockMsg = bitReader.readUnsigned(8); pXSprite->health = bitReader.readUnsigned(12); pXSprite->dudeDeaf = bitReader.readUnsigned(1); diff --git a/source/games/blood/src/loadsave.cpp b/source/games/blood/src/loadsave.cpp index 800ed00d4..40ba42072 100644 --- a/source/games/blood/src/loadsave.cpp +++ b/source/games/blood/src/loadsave.cpp @@ -642,9 +642,12 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, XSPRITE& w, XSPRIT ("lskill", w.lSkill, def->lSkill) ("lockmsg", w.lockMsg, def->lockMsg) ("dodgedir", w.dodgeDir, def->dodgeDir) - ("modernflags", w.unused1, def->unused1) - ("sightstuff", w.unused3, def->unused3) - ("patrolturndelay", w.unused4, def->unused4) + ("wave", w.wave, def->wave) + ("medium", w.medium, def->medium) + ("respawn", w.respawn, def->respawn) + ("modernflags", w.modernFlags, def->modernFlags) + ("sightstuff", w.sightstuff, def->sightstuff) + ("patrolturndelay", w.patrolturndelay, def->patrolturndelay) .EndObject(); } return arc; diff --git a/source/games/blood/src/mapstructs.h b/source/games/blood/src/mapstructs.h index 3605a18bc..d5f924b96 100644 --- a/source/games/blood/src/mapstructs.h +++ b/source/games/blood/src/mapstructs.h @@ -91,10 +91,7 @@ struct XSPRITE { unsigned int dudeAmbush : 1; // dudeAmbush unsigned int dudeGuard : 1; // dudeGuard unsigned int dudeFlag4 : 1; // unused - unsigned int wave : 2; // Wave - unsigned int medium : 2; // medium - unsigned int respawn : 2; // Respawn option - unsigned int unused2 : 1; // (new) patrol state + unsigned int patrolstate : 1; // (new) patrol state }; }; @@ -130,9 +127,13 @@ struct XSPRITE { uint8_t lSkill; // Launch 12345 uint8_t lockMsg; // Lock msg int8_t dodgeDir; // Dude dodge direction - uint8_t unused1; // modern flags - uint8_t unused3; // something about sight checks - uint8_t unused4; // patrol turn delay + uint8_t wave; // Wave + uint8_t medium; // medium + uint8_t respawn; // Respawn option + + uint8_t modernFlags; // modern flags + uint8_t sightstuff; // something about sight checks + uint8_t patrolturndelay; // patrol turn delay }; @@ -185,7 +186,7 @@ struct XSECTOR { unsigned int bobFloor : 1; // Motion bob floor unsigned int bobCeiling : 1; // Motion bob ceiling unsigned int bobRotate : 1; // Motion rotate - unsigned int unused1 : 1; // (new) pause motion + unsigned int pauseMotion : 1; // (new) pause motion }; }; DBloodActor* marker0; @@ -193,23 +194,23 @@ struct XSECTOR { DBloodActor* basePath; DBloodActor* actordata; - uint32_t busy; double offCeilZ; double onCeilZ; double offFloorZ; double onFloorZ; + DAngle panAngle; // Motion angle + DAngle windAng; // Wind ang uint32_t windVel; // Wind vel (changed from 10 bit to use higher velocity values) + uint32_t busy; uint16_t data; // Data uint16_t txID; // TX ID uint16_t rxID; // RX ID uint16_t busyTimeA; // OFF->ON busyTime uint16_t waitTimeA; // OFF->ON waitTime - DAngle panAngle; // Motion angle uint16_t busyTimeB; // ON->OFF busyTime uint16_t waitTimeB; // ON->OFF waitTime - DAngle windAng; // Wind ang uint16_t bobTheta; // Motion Theta int16_t bobSpeed; // Motion speed diff --git a/source/games/blood/src/nnexts.cpp b/source/games/blood/src/nnexts.cpp index 9c30a87b0..08c75f9aa 100644 --- a/source/games/blood/src/nnexts.cpp +++ b/source/games/blood/src/nnexts.cpp @@ -306,7 +306,7 @@ static DBloodActor* nnExtSpawnDude(DBloodActor* sourceactor, DBloodActor* origin pDudeActor->xspr.dudeGuard = sourceactor->xspr.dudeGuard; pDudeActor->xspr.dudeAmbush = sourceactor->xspr.dudeAmbush; pDudeActor->xspr.dudeFlag4 = sourceactor->xspr.dudeFlag4; - pDudeActor->xspr.unused1 = sourceactor->xspr.unused1; + pDudeActor->xspr.modernFlags = sourceactor->xspr.modernFlags; } @@ -762,7 +762,7 @@ void nnExtInitModernStuff(TArray& actors) } // make Sight, Screen, Aim flags work not just for dudes and things... - if ((actor->xspr.Sight || actor->xspr.unused3) && gSightSpritesCount < kMaxSuperXSprites) + if ((actor->xspr.Sight || actor->xspr.sightstuff) && gSightSpritesCount < kMaxSuperXSprites) { switch (actor->spr.statnum) { @@ -1204,7 +1204,7 @@ void nnExtProcessSuperSprites() pSight->xspr.isTriggered) continue; // don't process locked or triggered sprites // sprite is drawn for one of players - if ((pSight->xspr.unused3 & kTriggerSpriteScreen) && (pSight->spr.cstat2 & CSTAT2_SPRITE_MAPPED)) + if ((pSight->xspr.sightstuff & kTriggerSpriteScreen) && (pSight->spr.cstat2 & CSTAT2_SPRITE_MAPPED)) { trTriggerSprite(pSight, kCmdSpriteSight); pSight->spr.cstat2 &= ~CSTAT2_SPRITE_MAPPED; @@ -1230,7 +1230,7 @@ void nnExtProcessSuperSprites() trTriggerSprite(pSight, kCmdSpriteSight, plActor); } - if (pSight->xspr.unused3 & kTriggerSpriteAim) + if (pSight->xspr.sightstuff & kTriggerSpriteAim) { bool vector = (pSight->spr.cstat & CSTAT_SPRITE_BLOCK_HITSCAN); if (!vector) @@ -4232,7 +4232,7 @@ bool condCheckSector(DBloodActor* aCond, int cmpOp, bool PUSH) } } case 57: // this sector in movement? - return !pXSect->unused1; + return !pXSect->pauseMotion; } } else @@ -4462,7 +4462,7 @@ bool condCheckDude(DBloodActor* aCond, int cmpOp, bool PUSH) case 6: return objActor->xspr.dudeDeaf; case 7: return objActor->xspr.dudeGuard; case 8: return objActor->xspr.dudeAmbush; - case 9: return (objActor->xspr.unused1 & kDudeFlagStealth); + case 9: return (objActor->xspr.modernFlags & kDudeFlagStealth); case 10: // check if the marker is busy with another dude case 11: // check if the marker is reached if (!objActor->xspr.dudeFlag4 || !targ || targ->GetType() != kMarkerPath) return false; @@ -4482,7 +4482,7 @@ bool condCheckDude(DBloodActor* aCond, int cmpOp, bool PUSH) return true; case 12: // compare spot progress value in % if (!objActor->xspr.dudeFlag4 || !targ || targ->GetType() != kMarkerPath) var = 0; - else if (!(objActor->xspr.unused1 & kDudeFlagStealth) || objActor->xspr.data3 < 0 || objActor->xspr.data3 > kMaxPatrolSpotValue) var = 0; + else if (!(objActor->xspr.modernFlags & kDudeFlagStealth) || objActor->xspr.data3 < 0 || objActor->xspr.data3 > kMaxPatrolSpotValue) var = 0; else var = (kPercFull * objActor->xspr.data3) / kMaxPatrolSpotValue; return condCmp(var, arg1, arg2, cmpOp); case 15: return getDudeInfo(objActor)->lockOut; // dude allowed to interact with objects? @@ -5392,7 +5392,7 @@ void sectorPauseMotion(sectortype* pSector, DBloodActor* initiator) { if (!pSector->hasX()) return; XSECTOR* pXSector = &pSector->xs(); - pXSector->unused1 = 1; + pXSector->pauseMotion = 1; evKillSector(pSector, initiator); @@ -5412,7 +5412,7 @@ void sectorContinueMotion(sectortype* pSector, EVENT event) if (!pSector->hasX()) return; XSECTOR* pXSector = &pSector->xs(); - pXSector->unused1 = 0; + pXSector->pauseMotion = 0; int busyTimeA = pXSector->busyTimeA; int waitTimeA = pXSector->waitTimeA; @@ -5534,7 +5534,7 @@ bool modernTypeOperateSector(sectortype* pSector, const EVENT& event) // continue motion of the paused sector } - else if (pXSector->unused1) + else if (pXSector->pauseMotion) { switch (event.cmd) { @@ -7811,8 +7811,8 @@ void aiPatrolState(DBloodActor* actor, int state) if (actor->GetType() == kDudeModernCustom) aiGenDudeNewState(actor, newState); else aiNewState(actor, newState); - if (crouch) actor->xspr.unused1 |= kDudeFlagCrouch; - else actor->xspr.unused1 &= ~kDudeFlagCrouch; + if (crouch) actor->xspr.modernFlags |= kDudeFlagCrouch; + else actor->xspr.modernFlags &= ~kDudeFlagCrouch; if (nSeqOverride) seqSpawn(seq, actor); @@ -7986,11 +7986,11 @@ void aiPatrolSetMarker(DBloodActor* actor) } bool node = markerIsNode(targetactor, false); - actor->xspr.unused2 = aiPatrolGetPathDir(actor, targetactor); // decide if it should go back or forward - if (actor->xspr.unused2 == kPatrolMoveBackward && Chance(0x8000) && node) - actor->xspr.unused2 = kPatrolMoveForward; + actor->xspr.patrolstate = aiPatrolGetPathDir(actor, targetactor); // decide if it should go back or forward + if (actor->xspr.patrolstate == kPatrolMoveBackward && Chance(0x8000) && node) + actor->xspr.patrolstate = kPatrolMoveForward; - bool back = (actor->xspr.unused2 == kPatrolMoveBackward); next = (back) ? targetactor->xspr.data1 : targetactor->xspr.data2; + bool back = (actor->xspr.patrolstate == kPatrolMoveBackward); next = (back) ? targetactor->xspr.data1 : targetactor->xspr.data2; BloodStatIterator it(kStatPathMarker); while (auto nextactor = it.Next()) { @@ -8043,8 +8043,8 @@ void aiPatrolStop(DBloodActor* actor, DBloodActor* targetactor, bool alarm) if (actor->hasX()) { actor->xspr.data3 = 0; // reset spot progress - actor->xspr.unused1 &= ~kDudeFlagCrouch; // reset the crouch status - actor->xspr.unused2 = kPatrolMoveForward; // reset path direction + actor->xspr.modernFlags &= ~kDudeFlagCrouch; // reset the crouch status + actor->xspr.patrolstate = kPatrolMoveForward; // reset path direction actor->prevmarker = nullptr; actor->xspr.TargetPos.X = -1; // reset the previous marker index if (actor->xspr.health <= 0) @@ -8202,7 +8202,7 @@ void aiPatrolMove(DBloodActor* actor) actor->vel += actor->spr.Angles.Yaw.ToVector() * FixedToFloat(frontSpeed); } - double vel = (actor->xspr.unused1 & kDudeFlagCrouch) ? kMaxPatrolCrouchVelocity : kMaxPatrolVelocity; + double vel = (actor->xspr.modernFlags & kDudeFlagCrouch) ? kMaxPatrolCrouchVelocity : kMaxPatrolVelocity; vel *= dv.XY().Length() / 1024; // was: MulScale16 with length << 6, effectively resulting in >> 10. actor->vel.X = clamp(actor->vel.X, -vel, vel); @@ -8395,7 +8395,7 @@ DBloodActor* aiPatrolSearchTargets(DBloodActor* actor) } int i, mod, sndCnt = 0, seeChance, hearChance; - bool stealth = (actor->xspr.unused1 & kDudeFlagStealth); + bool stealth = (actor->xspr.modernFlags & kDudeFlagStealth); bool blind = (actor->xspr.dudeGuard); bool deaf = (actor->xspr.dudeDeaf); int nRandomSkill = Random(gGameOptions.nDifficulty); @@ -8715,10 +8715,10 @@ void aiPatrolFlagsMgr(DBloodActor* sourceactor, DBloodActor* destactor, bool cop destactor->xspr.dudeAmbush = sourceactor->xspr.dudeAmbush; destactor->xspr.dudeGuard = sourceactor->xspr.dudeGuard; destactor->xspr.dudeDeaf = sourceactor->xspr.dudeDeaf; - destactor->xspr.unused1 = sourceactor->xspr.unused1; + destactor->xspr.modernFlags = sourceactor->xspr.modernFlags; - if (sourceactor->xspr.unused1 & kDudeFlagStealth) destactor->xspr.unused1 |= kDudeFlagStealth; - else destactor->xspr.unused1 &= ~kDudeFlagStealth; + if (sourceactor->xspr.modernFlags & kDudeFlagStealth) destactor->xspr.modernFlags |= kDudeFlagStealth; + else destactor->xspr.modernFlags &= ~kDudeFlagStealth; } // do init @@ -8753,7 +8753,7 @@ void aiPatrolFlagsMgr(DBloodActor* sourceactor, DBloodActor* destactor, bool cop bool aiPatrolGetPathDir(DBloodActor* actor, DBloodActor* marker) { - if (actor->xspr.unused2 == kPatrolMoveForward) return (marker->xspr.data2 == -2) ? (bool)kPatrolMoveBackward : (bool)kPatrolMoveForward; + if (actor->xspr.patrolstate == kPatrolMoveForward) return (marker->xspr.data2 == -2) ? (bool)kPatrolMoveBackward : (bool)kPatrolMoveForward; else return (findNextMarker(marker, kPatrolMoveBackward) != nullptr) ? (bool)kPatrolMoveBackward : (bool)kPatrolMoveForward; } @@ -8777,7 +8777,7 @@ void aiPatrolThink(DBloodActor* actor) } - bool crouch = (actor->xspr.unused1 & kDudeFlagCrouch), uwater = spriteIsUnderwater(actor); + bool crouch = (actor->xspr.modernFlags & kDudeFlagCrouch), uwater = spriteIsUnderwater(actor); if (markeractor == nullptr || (actor->GetType() == kDudeModernCustom && ((uwater && !canSwim(actor)) || !canWalk(actor)))) { aiPatrolStop(actor, nullptr); @@ -8785,7 +8785,7 @@ void aiPatrolThink(DBloodActor* actor) } const DUDEINFO_EXTRA* pExtra = &gDudeInfoExtra[actor->GetType() - kDudeBase]; - bool isFinal = ((!actor->xspr.unused2 && markeractor->xspr.data2 == -1) || (actor->xspr.unused2 && markeractor->xspr.data1 == -1)); + bool isFinal = ((!actor->xspr.patrolstate && markeractor->xspr.data2 == -1) || (actor->xspr.patrolstate && markeractor->xspr.data1 == -1)); bool reached = false; if (aiPatrolWaiting(actor->xspr.aiState)) @@ -8802,12 +8802,12 @@ void aiPatrolThink(DBloodActor* actor) { stateTimer = actor->xspr.stateTimer; - if (--actor->xspr.unused4 <= 0) + if (--actor->xspr.patrolturndelay <= 0) { if (uwater) aiPatrolState(actor, kAiStatePatrolTurnW); else if (crouch) aiPatrolState(actor, kAiStatePatrolTurnC); else aiPatrolState(actor, kAiStatePatrolTurnL); - actor->xspr.unused4 = kMinPatrolTurnDelay + Random(kPatrolTurnDelayRange); + actor->xspr.patrolturndelay = kMinPatrolTurnDelay + Random(kPatrolTurnDelayRange); } // must restore stateTimer for waiting @@ -8879,7 +8879,7 @@ void aiPatrolThink(DBloodActor* actor) // take marker's angle if (!(markeractor->spr.flags & kModernTypeFlag4)) { - actor->xspr.goalAng = ((!(markeractor->spr.flags & kModernTypeFlag8) && actor->xspr.unused2) ? markeractor->spr.Angles.Yaw+ DAngle180 : markeractor->spr.Angles.Yaw).Normalized360(); + actor->xspr.goalAng = ((!(markeractor->spr.flags & kModernTypeFlag8) && actor->xspr.patrolstate) ? markeractor->spr.Angles.Yaw+ DAngle180 : markeractor->spr.Angles.Yaw).Normalized360(); if (absangle(actor->spr.Angles.Yaw, actor->xspr.goalAng) > minAngle) // let the enemy play move animation while turning return; } @@ -8912,7 +8912,7 @@ void aiPatrolThink(DBloodActor* actor) actor->xspr.stateTimer = (markeractor->xspr.waitTime * 120) / 10; if (markeractor->spr.flags & kModernTypeFlag16) - actor->xspr.unused4 = kMinPatrolTurnDelay + Random(kPatrolTurnDelayRange); + actor->xspr.patrolturndelay = kMinPatrolTurnDelay + Random(kPatrolTurnDelayRange); return; } diff --git a/source/games/blood/src/nnsprinsect.cpp b/source/games/blood/src/nnsprinsect.cpp index 5e49b8427..24dfb355e 100644 --- a/source/games/blood/src/nnsprinsect.cpp +++ b/source/games/blood/src/nnsprinsect.cpp @@ -172,7 +172,7 @@ bool isMovableSector(sectortype* pSect) { if (isMovableSector(pSect->type) && pSect->hasX()) { - return (pSect->xs().busy && !pSect->xs().unused1); + return (pSect->xs().busy && !pSect->xs().pauseMotion); } return false; } diff --git a/source/games/blood/src/triggers.cpp b/source/games/blood/src/triggers.cpp index 9777da168..1c4799c7b 100644 --- a/source/games/blood/src/triggers.cpp +++ b/source/games/blood/src/triggers.cpp @@ -1717,7 +1717,7 @@ void OperateSector(sectortype* pSector, EVENT event) break; default: #ifdef NOONE_EXTENSIONS - if (gModernMap && pXSector->unused1) break; + if (gModernMap && pXSector->pauseMotion) break; #endif switch (pSector->type) { case kSectorZMotionSprite: @@ -2205,7 +2205,7 @@ void trProcessBusy(void) int oldBusy = gBusy[i].busy; gBusy[i].busy = ClipRange(oldBusy + gBusy[i].delta * 4, 0, 65536); #ifdef NOONE_EXTENSIONS - if (!gModernMap || !gBusy[i].sect->xs().unused1) nStatus = gBusyProc[gBusy[i].type](gBusy[i].sect, gBusy[i].busy, nullptr); + if (!gModernMap || !gBusy[i].sect->xs().pauseMotion) nStatus = gBusyProc[gBusy[i].type](gBusy[i].sect, gBusy[i].busy, nullptr); else nStatus = 3; // allow to pause/continue motion for sectors any time by sending special command #else nStatus = gBusyProc[gBusy[i].type](gBusy[i].at0, gBusy[i].at8); diff --git a/source/games/blood/src/vmexports.cpp b/source/games/blood/src/vmexports.cpp index 53d5c31ce..5db47d3d2 100644 --- a/source/games/blood/src/vmexports.cpp +++ b/source/games/blood/src/vmexports.cpp @@ -4,13 +4,13 @@ Copyright (C) 2020-2023 - Christoph Oelckers This file is part of Raze -This is free software; you can redistribute it and/or +This is free software;you can redistribute it and/or modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 +as published by the Free Software Foundation;either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of +but WITHOUT ANY WARRANTY;without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -25,6 +25,57 @@ See the GNU General Public License for more details. BEGIN_BLD_NS +DEFINE_FIELD_X(XSECTOR, XSECTOR, flags) +DEFINE_FIELD_X(XSECTOR, XSECTOR, flags2) +DEFINE_FIELD_X(XSECTOR, XSECTOR, marker0) +DEFINE_FIELD_X(XSECTOR, XSECTOR, marker1) +DEFINE_FIELD_X(XSECTOR, XSECTOR, basePath) +DEFINE_FIELD_X(XSECTOR, XSECTOR, actordata) +DEFINE_FIELD_X(XSECTOR, XSECTOR, busy) +DEFINE_FIELD_X(XSECTOR, XSECTOR, offCeilZ) +DEFINE_FIELD_X(XSECTOR, XSECTOR, onCeilZ) +DEFINE_FIELD_X(XSECTOR, XSECTOR, offFloorZ) +DEFINE_FIELD_X(XSECTOR, XSECTOR, onFloorZ) +DEFINE_FIELD_X(XSECTOR, XSECTOR, windVel) +DEFINE_FIELD_X(XSECTOR, XSECTOR, data) +DEFINE_FIELD_X(XSECTOR, XSECTOR, txID) +DEFINE_FIELD_X(XSECTOR, XSECTOR, rxID) +DEFINE_FIELD_X(XSECTOR, XSECTOR, busyTimeA) +DEFINE_FIELD_X(XSECTOR, XSECTOR, waitTimeA) +DEFINE_FIELD_X(XSECTOR, XSECTOR, panAngle) +DEFINE_FIELD_X(XSECTOR, XSECTOR, busyTimeB) +DEFINE_FIELD_X(XSECTOR, XSECTOR, waitTimeB) +DEFINE_FIELD_X(XSECTOR, XSECTOR, windAng) +DEFINE_FIELD_X(XSECTOR, XSECTOR, bobTheta) +DEFINE_FIELD_X(XSECTOR, XSECTOR, bobSpeed) +DEFINE_FIELD_X(XSECTOR, XSECTOR, busyWaveA) +DEFINE_FIELD_X(XSECTOR, XSECTOR, busyWaveB) +DEFINE_FIELD_X(XSECTOR, XSECTOR, command) +DEFINE_FIELD_X(XSECTOR, XSECTOR, amplitude) +DEFINE_FIELD_X(XSECTOR, XSECTOR, freq) +DEFINE_FIELD_X(XSECTOR, XSECTOR, phase) +DEFINE_FIELD_X(XSECTOR, XSECTOR, wave) +DEFINE_FIELD_X(XSECTOR, XSECTOR, shade) +DEFINE_FIELD_X(XSECTOR, XSECTOR, panVel) +DEFINE_FIELD_X(XSECTOR, XSECTOR, Depth) +DEFINE_FIELD_X(XSECTOR, XSECTOR, Key) +DEFINE_FIELD_X(XSECTOR, XSECTOR, ceilpal) +DEFINE_FIELD_X(XSECTOR, XSECTOR, damageType) +DEFINE_FIELD_X(XSECTOR, XSECTOR, floorpal) +DEFINE_FIELD_X(XSECTOR, XSECTOR, bobZRange) + +DEFINE_FIELD_X(XWALL, XWALL, flags) +DEFINE_FIELD_X(XWALL, XWALL, busy) +DEFINE_FIELD_X(XWALL, XWALL, data) +DEFINE_FIELD_X(XWALL, XWALL, txID) +DEFINE_FIELD_X(XWALL, XWALL, rxID) +DEFINE_FIELD_X(XWALL, XWALL, busyTime) +DEFINE_FIELD_X(XWALL, XWALL, waitTime) +DEFINE_FIELD_X(XWALL, XWALL, command) +DEFINE_FIELD_NAMED_X(XWALL, XWALL, panVel.X, panVelX) // VM does not support int vectors. +DEFINE_FIELD_NAMED_X(XWALL, XWALL, panVel.Y, panVelY) +DEFINE_FIELD_X(XWALL, XWALL, key) + void Blood_ChangeType(DBloodActor* self, PClassActor* type) { diff --git a/wadsrc/static/zscript/games/maptypes.zs b/wadsrc/static/zscript/games/maptypes.zs index 4863caccb..1afd1cc43 100644 --- a/wadsrc/static/zscript/games/maptypes.zs +++ b/wadsrc/static/zscript/games/maptypes.zs @@ -110,6 +110,93 @@ enum ESectorExBits +//============================================================================= +// +// Blood's sector extension. +// +//============================================================================= + +struct XSECTOR native +{ + native uint flags; + native int flags2; + native BloodActor marker0; + native BloodActor marker1; + native BloodActor basePath; + native BloodActor actordata; + native uint busy; + native double offCeilZ; + native double onCeilZ; + native double offFloorZ; + native double onFloorZ; + native uint windVel; + native uint16 data; + native uint16 txID; + native uint16 rxID; + native uint16 busyTimeA; + native uint16 waitTimeA; + native double panAngle; + native uint16 busyTimeB; + native uint16 waitTimeB; + native double windAng; + native uint16 bobTheta; + native int16 bobSpeed; + native uint8 busyWaveA; + native uint8 busyWaveB; + native uint8 command; + native int8 amplitude; + native uint8 freq; + native uint8 phase; + native uint8 wave; + native int8 shade; + native uint8 panVel; + native uint8 Depth; + native uint8 Key; + native uint8 ceilpal; + native uint8 damageType; + native uint8 floorpal; + native uint8 bobZRange; + + flagdef internal state: flags, 0; + flagdef internal triggerOn: flags, 1; + flagdef internal triggerOff: flags, 2; + flagdef internal restState: flags, 3; + flagdef internal interruptable: flags, 4; + flagdef internal reTriggerA: flags, 5; + flagdef internal reTriggerB: flags, 6; + flagdef internal shadeAlways: flags, 7; + flagdef internal shadeFloor: flags, 8; + flagdef internal shadeCeiling: flags, 9; + flagdef internal shadeWalls: flags, 10; + flagdef internal panAlways: flags, 11; + flagdef internal panFloor: flags, 12; + flagdef internal panCeiling: flags, 13; + flagdef internal Drag: flags, 14; + flagdef internal Underwater: flags, 15; + flagdef internal decoupled: flags, 16; + flagdef internal triggerOnce: flags, 17; + flagdef internal isTriggered: flags, 18; + flagdef internal Push: flags, 19; + flagdef internal Vector: flags, 20; + flagdef internal Reserved: flags, 21; + flagdef internal Enter: flags, 22; + flagdef internal Exit: flags, 23; + flagdef internal Wallpush: flags, 24; + flagdef internal color: flags, 25; + flagdef internal stopOn: flags, 26; + flagdef internal stopOff: flags, 27; + flagdef internal Crush: flags, 28; + flagdef internal locked: flags, 29; + flagdef internal windAlways: flags, 30; + + flagdef internal dudeLockout: flags2, 0; + flagdef internal bobAlways: flags2, 1; + flagdef internal bobFloor: flags2, 2; + flagdef internal bobCeiling: flags2, 3; + flagdef internal bobRotate: flags2, 4; + flagdef internal pauseMotion: flags2, 5; +} + //============================================================================= // // internal sector struct - no longer identical with on-disk format @@ -177,7 +264,7 @@ struct sectortype native native uint8 shadedsector; DukeActor hitagactor; // we need this because Duke stores an actor in the hitag field. Is really a DDukeActor, but cannot be declared here safely. - //native XSECTOR x; + native XSECTOR x; native BloodActor upperLink; native BloodActor lowerLink; native double baseFloor; @@ -244,6 +331,43 @@ struct sectortype native } +//============================================================================= +// +// Blood's wall extension. +// +//============================================================================= + + +struct XWALL native { + + native uint flags; + native uint busy; + native int16 data; + native uint16 txID; + native uint16 rxID; + native uint16 busyTime; + native uint16 waitTime; + native uint8 command; + native int panVelX; + native int panVelY; + native uint8 key; + + flagdef internal state: flags, 0; + flagdef internal triggerOn: flags, 1; + flagdef internal triggerOff: flags, 2; + flagdef internal restState: flags, 3; + flagdef internal interruptable: flags, 4; + flagdef internal panAlways: flags, 5; + flagdef internal decoupled: flags, 6; + flagdef internal triggerOnce: flags, 7; + flagdef internal isTriggered: flags, 8; + flagdef internal triggerPush: flags, 9; + flagdef internal triggerVector: flags, 10; + flagdef internal triggerTouch: flags, 11; + flagdef internal locked: flags, 12; + flagdef internal dudeLockout: flags, 13; +} + //============================================================================= // // internal wall struct - no longer identical with on-disk format @@ -281,7 +405,7 @@ struct walltype native //native uint8 xrepeat; // these are still bytes, do not export unless floatified //native uint8 yrepeat; - //native XWALL x; + native XWALL x; native void setxpan(double add);