diff --git a/source/core/codegen_raze.cpp b/source/core/codegen_raze.cpp index 92952f617..cd0fbf862 100644 --- a/source/core/codegen_raze.cpp +++ b/source/core/codegen_raze.cpp @@ -46,6 +46,7 @@ #include "v_font.h" #include "gamecontrol.h" #include "gi.h" +#include "games/duke/src/duke3d.h" PFunction* FindBuiltinFunction(FName funcname); @@ -177,14 +178,81 @@ static FxExpression *ResolveGlobalCustomFunction(FxFunctionCall *func, FCompileC return newfunc->Resolve(ctx); } } + // the following 3 are just for compile time argument validation, they do not affect code generation. else if (func->MethodName == NAME_SetAction && isDukeEngine()) { + auto cls = ctx.Function->Variants[0].SelfClass; + if (cls == nullptr || !cls->isClass()) return func; + auto clas = static_cast(cls)->Descriptor; + if (!clas->IsDescendantOf(RUNTIME_CLASS(Duke3d::DDukeActor))) return func; + if (CheckArgSize(NAME_SetAction, func->ArgList, 1, 1, ScriptPosition)) + { + FxExpression* x; + x = func->ArgList[0] = func->ArgList[0]->Resolve(ctx); + if (x && x->isConstant() && (x->ValueType == TypeName || x->ValueType == TypeString)) + { + auto c = static_cast(x); + auto nm = c->GetValue().GetName(); + if (nm == NAME_None) return func; + int pos = Duke3d::LookupAction(clas, nm); + if (pos == 0) + { + ScriptPosition.Message(MSG_ERROR, "Invalid action '%s'", nm.GetChars()); + delete func; + return nullptr; + } + } + } } else if (func->MethodName == NAME_SetAI && isDukeEngine()) { + auto cls = ctx.Function->Variants[0].SelfClass; + if (cls == nullptr || !cls->isClass()) return func; + auto clas = static_cast(cls)->Descriptor; + if (!clas->IsDescendantOf(RUNTIME_CLASS(Duke3d::DDukeActor))) return func; + if (CheckArgSize(NAME_SetAI, func->ArgList, 1, 1, ScriptPosition)) + { + FxExpression* x; + x = func->ArgList[0] = func->ArgList[0]->Resolve(ctx); + if (x && x->isConstant() && (x->ValueType == TypeName || x->ValueType == TypeString)) + { + auto c = static_cast(x); + auto nm = c->GetValue().GetName(); + if (nm == NAME_None) return func; + int pos = Duke3d::LookupAI(clas, nm); + if (pos == 0) + { + ScriptPosition.Message(MSG_ERROR, "Invalid AI '%s'", nm.GetChars()); + delete func; + return nullptr; + } + } + } } else if (func->MethodName == NAME_SetMove && isDukeEngine()) { + auto cls = ctx.Function->Variants[0].SelfClass; + if (cls == nullptr || !cls->isClass()) return func; + auto clas = static_cast(cls)->Descriptor; + if (!clas->IsDescendantOf(RUNTIME_CLASS(Duke3d::DDukeActor))) return func; + if (CheckArgSize(NAME_SetMove, func->ArgList, 1, 2, ScriptPosition)) + { + FxExpression* x; + x = func->ArgList[0] = func->ArgList[0]->Resolve(ctx); + if (x && x->isConstant() && (x->ValueType == TypeName || x->ValueType == TypeString)) + { + auto c = static_cast(x); + auto nm = c->GetValue().GetName(); + if (nm == NAME_None) return func; + int pos = Duke3d::LookupMove(clas, nm); + if (pos == 0) + { + ScriptPosition.Message(MSG_ERROR, "Invalid move '%s'", nm.GetChars()); + delete func; + return nullptr; + } + } + } } // most of these can be resolved right here. Only isWorldTour, isPlutoPak and isShareware can not if Duke is being played. else if (func->MethodName == NAME_isDuke) @@ -258,152 +326,6 @@ static FxExpression *ResolveGlobalCustomFunction(FxFunctionCall *func, FCompileC return func; } - - -//========================================================================== -// -// FxSetActionCall -// -//========================================================================== - -FxSetActionCall::FxSetActionCall(FxExpression *self, FxExpression* arg, const FScriptPosition &pos) -: FxExpression(EFX_ActionSpecialCall, pos) -{ - Self = self; - Arg = arg; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxSetActionCall::~FxSetActionCall() -{ - SAFE_DELETE(Self); -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxSetActionCall::Resolve(FCompileContext& ctx) -{ - CHECKRESOLVED(); - return this; -} - - -//========================================================================== -// -// -// -//========================================================================== - -ExpEmit FxSetActionCall::Emit(VMFunctionBuilder *build) -{ - return ExpEmit(); -} - -//========================================================================== -// -// FxSetAICall -// -//========================================================================== - -FxSetAICall::FxSetAICall(FxExpression *self, FxExpression* arg, const FScriptPosition &pos) -: FxExpression(EFX_ActionSpecialCall, pos) -{ - Self = self; - Arg = arg; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxSetAICall::~FxSetAICall() -{ - SAFE_DELETE(Self); -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxSetAICall::Resolve(FCompileContext& ctx) -{ - CHECKRESOLVED(); - return this; -} - - -//========================================================================== -// -// -// -//========================================================================== - -ExpEmit FxSetAICall::Emit(VMFunctionBuilder *build) -{ - return ExpEmit(); -} - -//========================================================================== -// -// FxSetMoveCall -// -//========================================================================== - -FxSetMoveCall::FxSetMoveCall(FxExpression *self, FxExpression* arg, const FScriptPosition &pos) -: FxExpression(EFX_ActionSpecialCall, pos) -{ - Self = self; - Arg = arg; -} - -//========================================================================== -// -// -// -//========================================================================== - -FxSetMoveCall::~FxSetMoveCall() -{ - SAFE_DELETE(Self); -} - -//========================================================================== -// -// -// -//========================================================================== - -FxExpression *FxSetMoveCall::Resolve(FCompileContext& ctx) -{ - CHECKRESOLVED(); - return this; -} - - -//========================================================================== -// -// -// -//========================================================================== - -ExpEmit FxSetMoveCall::Emit(VMFunctionBuilder *build) -{ - return ExpEmit(); -} - //========================================================================== // // code generation is only performed for some Duke checks that depend on CON diff --git a/source/core/codegen_raze.h b/source/core/codegen_raze.h index 1a02a4324..76383f659 100644 --- a/source/core/codegen_raze.h +++ b/source/core/codegen_raze.h @@ -2,62 +2,6 @@ #include "codegen.h" #include "coreactor.h" -//========================================================================== -// -// -// -//========================================================================== - -class FxSetActionCall : public FxExpression -{ - FxExpression *Self; - FxExpression *Arg; - -public: - - FxSetActionCall(FxExpression *self, FxExpression* arg, const FScriptPosition &pos); - ~FxSetActionCall(); - FxExpression *Resolve(FCompileContext&); - ExpEmit Emit(VMFunctionBuilder *build); -}; - -//========================================================================== -// -// -// -//========================================================================== - -class FxSetAICall : public FxExpression -{ - FxExpression *Self; - FxExpression *Arg; - -public: - - FxSetAICall(FxExpression *self, FxExpression* arg, const FScriptPosition &pos); - ~FxSetAICall(); - FxExpression *Resolve(FCompileContext&); - ExpEmit Emit(VMFunctionBuilder *build); -}; - -//========================================================================== -// -// -// -//========================================================================== - -class FxSetMoveCall : public FxExpression -{ - FxExpression *Self; - FxExpression *Arg; - -public: - - FxSetMoveCall(FxExpression *self, FxExpression* arg, const FScriptPosition &pos); - ~FxSetMoveCall(); - FxExpression *Resolve(FCompileContext&); - ExpEmit Emit(VMFunctionBuilder *build); -}; //========================================================================== // diff --git a/source/core/namedef_custom.h b/source/core/namedef_custom.h index 4e5359367..c228376c9 100644 --- a/source/core/namedef_custom.h +++ b/source/core/namedef_custom.h @@ -1,5 +1,6 @@ // Raze specific names - +xx(0) +xx(no) xx(IngameMenu) xx(ListMenuItemBloodDripDrawer) xx(UsermapMenu) @@ -53,3 +54,6 @@ xx(isDukeEngine) xx(isBlood) xx(isSW) xx(isExhumed) +xx(ChangeAction) +xx(ChangeAI) +xx(ChangeMove) diff --git a/source/games/duke/src/funct.h b/source/games/duke/src/funct.h index bd4d5f130..0a894f3a4 100644 --- a/source/games/duke/src/funct.h +++ b/source/games/duke/src/funct.h @@ -247,9 +247,9 @@ bool checkhitswitch(int snum, walltype* wwal, DDukeActor* act); void drawshadows(tspriteArray& tsprites, tspritetype* t, DDukeActor* h); void applyanimations(tspritetype* t, DDukeActor* h, const DVector2& viewVec, DAngle viewang); -int LookupAction(DDukeActor* self, FName name); -int LookupMove(DDukeActor* self, FName name); -int LookupAI(DDukeActor* self, FName name); +int LookupAction(PClass* self, FName name); +int LookupMove(PClass* self, FName name); +int LookupAI(PClass* self, FName name); inline int32_t krand(void) diff --git a/source/games/duke/src/game.cpp b/source/games/duke/src/game.cpp index 75e8365bc..59a16dfcd 100644 --- a/source/games/duke/src/game.cpp +++ b/source/games/duke/src/game.cpp @@ -506,22 +506,46 @@ void GameInterface::FinalizeSetup() } -int LookupAction(DDukeActor* self, FName name) +int LookupAction(PClass* cls, FName name) { - // todo - return 0; + while (true) + { + auto ainf = static_cast(cls)->ActorInfo(); + for (int i = 0; i < ainf->NumActions; i++) + { + if (actions[ainf->FirstAction + i].name == name) return ainf->FirstAction + i; + } + if (cls == RUNTIME_CLASS(DDukeActor)) return 0; + cls = cls->ParentClass; + } } -int LookupMove(DDukeActor* self, FName name) +int LookupMove(PClass* cls, FName name) { - // todo - return 0; + while (true) + { + auto ainf = static_cast(cls)->ActorInfo(); + for (int i = 0; i < ainf->NumMoves; i++) + { + if (actions[ainf->FirstMove + i].name == name) return ainf->FirstMove + i; + } + if (cls == RUNTIME_CLASS(DDukeActor)) return 0; + cls = cls->ParentClass; + } } -int LookupAI(DDukeActor* self, FName name) +int LookupAI(PClass* cls, FName name) { - // todo - return 0; + while (true) + { + auto ainf = static_cast(cls)->ActorInfo(); + for (int i = 0; i < ainf->NumAIs; i++) + { + if (actions[ainf->FirstAI + i].name == name) return ainf->FirstAI + i; + } + if (cls == RUNTIME_CLASS(DDukeActor)) return 0; + cls = cls->ParentClass; + } } diff --git a/source/games/duke/src/vmexports.cpp b/source/games/duke/src/vmexports.cpp index ab021d4d9..62139a1f8 100644 --- a/source/games/duke/src/vmexports.cpp +++ b/source/games/duke/src/vmexports.cpp @@ -714,8 +714,10 @@ DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, aim, aim_) void Duke_SetAction(DDukeActor* self, int intname) { - int ndx = LookupAction(self, FName(ENamedName(intname))); + int ndx = LookupAction(self->GetClass(), FName(ENamedName(intname))); self->curAction = &actions[ndx]; + self->actioncounter = self->curframe = 0; + } DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, SetAction, Duke_SetAction) @@ -728,7 +730,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, SetAction, Duke_SetAction) void Duke_SetMove(DDukeActor* self, int intname, int flags) { - int ndx = LookupMove(self, FName(ENamedName(intname))); + int ndx = LookupMove(self->GetClass(), FName(ENamedName(intname))); self->curMove = &moves[ndx]; self->spr.hitag = flags; } @@ -744,11 +746,15 @@ DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, SetMove, Duke_SetMove) void Duke_SetAI(DDukeActor* self, int intname) { - int ndx = LookupAI(self, FName(ENamedName(intname))); + int ndx = LookupAI(self->GetClass(), FName(ENamedName(intname))); self->curMove = &moves[ais[ndx].move]; self->curAction = &actions[ais[ndx].action]; self->spr.hitag = ais[ndx].moveflags; self->curAI = ais[ndx].name; + self->actioncounter = self->curframe = 0; + self->counter = 0; + if (self->spr.hitag & random_angle) + self->spr.Angles.Yaw = randomAngle(); } DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, SetAI, Duke_SetAI)