mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-10 14:51:40 +00:00
A_ChangeModeldef
-Added A_ChangeModelDef A_ChangeModel(modeldef, modelpath, model, modelindex, skinpath, skin, skinid, flags) This can change the modeldef, model and skins of an actor. Currently, modelindex and skinindex accept indices from 0-15. An actor MUST have a modeldef in order to use this function, either defined from modeldef, or given one through the modeldef parameter. You can pass "" to use the same modeldef. Likewise, passing "" for model or skin will just revert to the default model. Available flags: CMDL_WEAPONTOPLAYER - If used on a weapon, this instead change's the model on the player instead. One issue I am aware of right now is that clearing a model by "" sort of works but is buggy. For now you can just manually set the model back using the names explicitly. However, I am stumped and I think getting more eyes on it would help.
This commit is contained in:
parent
e649357d4e
commit
5abadd3aab
6 changed files with 60 additions and 7 deletions
|
@ -1068,6 +1068,9 @@ public:
|
||||||
DVector3 WorldOffset;
|
DVector3 WorldOffset;
|
||||||
double Speed;
|
double Speed;
|
||||||
double FloatSpeed;
|
double FloatSpeed;
|
||||||
|
FName modelDef;
|
||||||
|
int models[16] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; //[SM] - I hate this solution, but it get's the job done
|
||||||
|
FTextureID skins[16];
|
||||||
|
|
||||||
// interaction info
|
// interaction info
|
||||||
FBlockNode *BlockNode; // links in blocks (if needed)
|
FBlockNode *BlockNode; // links in blocks (if needed)
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
#include "sbar.h"
|
#include "sbar.h"
|
||||||
#include "actorinlines.h"
|
#include "actorinlines.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
#include "model.h"
|
||||||
|
|
||||||
static FRandom pr_camissile ("CustomActorfire");
|
static FRandom pr_camissile ("CustomActorfire");
|
||||||
static FRandom pr_cabullet ("CustomBullet");
|
static FRandom pr_cabullet ("CustomBullet");
|
||||||
|
@ -5020,6 +5021,46 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetMugshotState)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// A_ChangeModel(modeldef, modelpath, model, modelindex, skinpath, skin, skinid, flags)
|
||||||
|
//
|
||||||
|
// This function allows the changing of an actor's modeldef, or models and/or skins at a given index
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
enum ChangeModelFlags
|
||||||
|
{
|
||||||
|
CMDL_WEAPONTOPLAYER = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(AActor, A_ChangeModel)
|
||||||
|
{
|
||||||
|
PARAM_ACTION_PROLOGUE(AActor);
|
||||||
|
PARAM_NAME(modeldef)
|
||||||
|
PARAM_STRING_VAL(modelpath)
|
||||||
|
PARAM_NAME(model)
|
||||||
|
PARAM_INT(modelindex)
|
||||||
|
PARAM_STRING_VAL(skinpath)
|
||||||
|
PARAM_NAME(skin)
|
||||||
|
PARAM_INT(skinindex)
|
||||||
|
PARAM_INT(flags)
|
||||||
|
|
||||||
|
if (self == nullptr)
|
||||||
|
ACTION_RETURN_BOOL(false);
|
||||||
|
|
||||||
|
AActor* mobj = ACTION_CALL_FROM_PSPRITE() && (flags & CMDL_WEAPONTOPLAYER) ? self : stateowner;
|
||||||
|
|
||||||
|
if (modelpath[(int)modelpath.Len() - 1] != '/') modelpath += '/';
|
||||||
|
if (skinpath[(int)skinpath.Len() - 1] != '/') skinpath += '/';
|
||||||
|
|
||||||
|
mobj->hasmodel = modeldef == nullptr && !mobj->hasmodel ? 1 : 0;
|
||||||
|
mobj->modelDef = modeldef;
|
||||||
|
mobj->models[modelindex] = model != nullptr ? FindModel(modelpath.GetChars(), model.GetChars()) : -1;
|
||||||
|
mobj->skins[skinindex] = skin != nullptr ? LoadSkin(skinpath.GetChars(), skin.GetChars()) : mobj->skins[skinindex] = FNullTextureID();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// This needs to account for the fact that internally renderstyles are stored as a series of operations,
|
// This needs to account for the fact that internally renderstyles are stored as a series of operations,
|
||||||
// but the script side only cares about symbolic constants.
|
// but the script side only cares about symbolic constants.
|
||||||
DEFINE_ACTION_FUNCTION(AActor, GetRenderStyle)
|
DEFINE_ACTION_FUNCTION(AActor, GetRenderStyle)
|
||||||
|
|
|
@ -55,7 +55,7 @@ EXTERN_CVAR (Bool, r_drawvoxels)
|
||||||
extern TDeletingArray<FVoxel *> Voxels;
|
extern TDeletingArray<FVoxel *> Voxels;
|
||||||
extern TDeletingArray<FVoxelDef *> VoxelDefs;
|
extern TDeletingArray<FVoxelDef *> VoxelDefs;
|
||||||
|
|
||||||
void RenderFrameModels(FModelRenderer* renderer, FLevelLocals* Level, const FSpriteModelFrame* smf, const FState* curState, const int curTics, const PClass* ti, int translation);
|
void RenderFrameModels(FModelRenderer* renderer, FLevelLocals* Level, const FSpriteModelFrame* smf, const FState* curState, const int curTics, const PClass* ti, int translation, AActor* actor);
|
||||||
|
|
||||||
|
|
||||||
void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor, double ticFrac)
|
void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor, double ticFrac)
|
||||||
|
@ -176,14 +176,14 @@ void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteMod
|
||||||
float orientation = scaleFactorX * scaleFactorY * scaleFactorZ;
|
float orientation = scaleFactorX * scaleFactorY * scaleFactorZ;
|
||||||
|
|
||||||
renderer->BeginDrawModel(actor->RenderStyle, smf, objectToWorldMatrix, orientation < 0);
|
renderer->BeginDrawModel(actor->RenderStyle, smf, objectToWorldMatrix, orientation < 0);
|
||||||
RenderFrameModels(renderer, actor->Level, smf, actor->state, actor->tics, actor->GetClass(), translation);
|
RenderFrameModels(renderer, actor->Level, smf, actor->state, actor->tics, actor->modelDef != nullptr ? PClass::FindActor(actor->modelDef) : actor->GetClass(), translation, actor);
|
||||||
renderer->EndDrawModel(actor->RenderStyle, smf);
|
renderer->EndDrawModel(actor->RenderStyle, smf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderHUDModel(FModelRenderer *renderer, DPSprite *psp, float ofsX, float ofsY)
|
void RenderHUDModel(FModelRenderer *renderer, DPSprite *psp, float ofsX, float ofsY)
|
||||||
{
|
{
|
||||||
AActor * playermo = players[consoleplayer].camera;
|
AActor * playermo = players[consoleplayer].camera;
|
||||||
FSpriteModelFrame *smf = psp->Caller != nullptr ? FindModelFrame(psp->Caller->GetClass(), psp->GetSprite(), psp->GetFrame(), false) : nullptr;
|
FSpriteModelFrame *smf = psp->Caller != nullptr ? FindModelFrame(psp->Caller->modelDef != nullptr ? PClass::FindActor(psp->Caller->modelDef) : psp->Caller->GetClass(), psp->GetSprite(), psp->GetFrame(), false) : nullptr;
|
||||||
|
|
||||||
// [BB] No model found for this sprite, so we can't render anything.
|
// [BB] No model found for this sprite, so we can't render anything.
|
||||||
if (smf == nullptr)
|
if (smf == nullptr)
|
||||||
|
@ -224,11 +224,11 @@ void RenderHUDModel(FModelRenderer *renderer, DPSprite *psp, float ofsX, float o
|
||||||
renderer->BeginDrawHUDModel(playermo->RenderStyle, objectToWorldMatrix, orientation < 0);
|
renderer->BeginDrawHUDModel(playermo->RenderStyle, objectToWorldMatrix, orientation < 0);
|
||||||
uint32_t trans = psp->GetTranslation() != 0 ? psp->GetTranslation() : 0;
|
uint32_t trans = psp->GetTranslation() != 0 ? psp->GetTranslation() : 0;
|
||||||
if ((psp->Flags & PSPF_PLAYERTRANSLATED)) trans = psp->Owner->mo->Translation;
|
if ((psp->Flags & PSPF_PLAYERTRANSLATED)) trans = psp->Owner->mo->Translation;
|
||||||
RenderFrameModels(renderer, playermo->Level, smf, psp->GetState(), psp->GetTics(), psp->Caller->GetClass(), trans);
|
RenderFrameModels(renderer, playermo->Level, smf, psp->GetState(), psp->GetTics(), psp->Caller->modelDef != nullptr ? PClass::FindActor(psp->Caller->modelDef) : psp->Caller->GetClass(), trans, psp->Caller);
|
||||||
renderer->EndDrawHUDModel(playermo->RenderStyle);
|
renderer->EndDrawHUDModel(playermo->RenderStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpriteModelFrame *smf, const FState *curState, const int curTics, const PClass *ti, int translation)
|
void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpriteModelFrame *smf, const FState *curState, const int curTics, const PClass *ti, int translation, AActor* actor)
|
||||||
{
|
{
|
||||||
// [BB] Frame interpolation: Find the FSpriteModelFrame smfNext which follows after smf in the animation
|
// [BB] Frame interpolation: Find the FSpriteModelFrame smfNext which follows after smf in the animation
|
||||||
// and the scalar value inter ( element of [0,1) ), both necessary to determine the interpolated frame.
|
// and the scalar value inter ( element of [0,1) ), both necessary to determine the interpolated frame.
|
||||||
|
@ -278,10 +278,12 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
|
||||||
|
|
||||||
for (int i = 0; i < smf->modelsAmount; i++)
|
for (int i = 0; i < smf->modelsAmount; i++)
|
||||||
{
|
{
|
||||||
|
if (actor->models[i] != -1)
|
||||||
|
smf->modelIDs[i] = actor->models[i];
|
||||||
if (smf->modelIDs[i] != -1)
|
if (smf->modelIDs[i] != -1)
|
||||||
{
|
{
|
||||||
FModel * mdl = Models[smf->modelIDs[i]];
|
FModel * mdl = Models[smf->modelIDs[i]];
|
||||||
auto tex = smf->skinIDs[i].isValid() ? TexMan.GetGameTexture(smf->skinIDs[i], true) : nullptr;
|
auto tex = actor->skins[i].isValid() ? TexMan.GetGameTexture(actor->skins[i], true) : smf->skinIDs[i].isValid() ? TexMan.GetGameTexture(smf->skinIDs[i], true) : nullptr;
|
||||||
mdl->BuildVertexBuffer(renderer);
|
mdl->BuildVertexBuffer(renderer);
|
||||||
|
|
||||||
mdl->PushSpriteMDLFrame(smf, i);
|
mdl->PushSpriteMDLFrame(smf, i);
|
||||||
|
|
|
@ -834,7 +834,7 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
|
||||||
z += fz;
|
z += fz;
|
||||||
}
|
}
|
||||||
|
|
||||||
modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED));
|
modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing->modelDef != nullptr ? PClass::FindActor(thing->modelDef) : thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED));
|
||||||
|
|
||||||
// don't bother drawing sprite shadows if this is a model (it will never look right)
|
// don't bother drawing sprite shadows if this is a model (it will never look right)
|
||||||
if (modelframe && isSpriteShadow)
|
if (modelframe && isSpriteShadow)
|
||||||
|
|
|
@ -1132,6 +1132,7 @@ class Actor : Thinker native
|
||||||
native void A_SetBlend(color color1, double alpha, int tics, color color2 = 0, double alpha2 = 0.);
|
native void A_SetBlend(color color1, double alpha, int tics, color color2 = 0, double alpha2 = 0.);
|
||||||
deprecated("2.3", "Use 'b<FlagName> = [true/false]' instead") native void A_ChangeFlag(string flagname, bool value);
|
deprecated("2.3", "Use 'b<FlagName> = [true/false]' instead") native void A_ChangeFlag(string flagname, bool value);
|
||||||
native void A_ChangeCountFlags(int kill = FLAG_NO_CHANGE, int item = FLAG_NO_CHANGE, int secret = FLAG_NO_CHANGE);
|
native void A_ChangeCountFlags(int kill = FLAG_NO_CHANGE, int item = FLAG_NO_CHANGE, int secret = FLAG_NO_CHANGE);
|
||||||
|
action native void A_ChangeModel(name modeldef, string modelpath = "", name model = "", int modelindex = 0, string skinpath = "", name skin = "", int skinindex = 0, int flags = 0);
|
||||||
|
|
||||||
void A_SetFriendly (bool set)
|
void A_SetFriendly (bool set)
|
||||||
{
|
{
|
||||||
|
|
|
@ -365,6 +365,12 @@ enum ERadiusGiveFlags
|
||||||
RGF_EITHER = 1 << 17,
|
RGF_EITHER = 1 << 17,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Change model flags
|
||||||
|
enum ChangeModelFlags
|
||||||
|
{
|
||||||
|
CMDL_WEAPONTOPLAYER = 1
|
||||||
|
};
|
||||||
|
|
||||||
// Activation flags
|
// Activation flags
|
||||||
enum EActivationFlags
|
enum EActivationFlags
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue