bool AWeapon::TryPickup (AActor *&toucher) { FState * ReadyState = FindState(NAME_Ready); if (ReadyState != NULL && ReadyState->GetFrame() < sprites[ReadyState->sprite].numframes) { return Super::TryPickup (toucher); } return false; }
bool gl_IsHUDModelForPlayerAvailable (player_t * player) { if ( (player == NULL) || (player->ReadyWeapon == NULL) || (player->psprites[0].state == NULL) ) return false; FState* state = player->psprites[0].state; FSpriteModelFrame *smf = gl_FindModelFrame(player->ReadyWeapon->GetClass(), state->sprite, state->GetFrame()); return ( smf != NULL ); }
END_DEFAULTS bool APainElemental::Massacre () { if (Super::Massacre ()) { FState *deadstate; A_NoBlocking (this); // [RH] Use this instead of A_PainDie deadstate = DeathState; if (deadstate != NULL) { while (deadstate->GetNextState() != NULL) deadstate = deadstate->GetNextState(); SetState (deadstate); } return true; } return false; }
bool gl_IsHUDModelForPlayerAvailable (player_t * player) { if (player == nullptr || player->ReadyWeapon == nullptr) return false; DPSprite *psp = player->FindPSprite(PSP_WEAPON); if (psp == nullptr || psp->GetState() == nullptr) return false; FState* state = psp->GetState(); FSpriteModelFrame *smf = gl_FindModelFrame(player->ReadyWeapon->GetClass(), state->sprite, state->GetFrame(), false); return ( smf != nullptr ); }
static void DrawOneKey(int xo, int & x, int & y, int & c, AInventory * inv) { FTextureID icon = FNullTextureID(); FTextureID AltIcon = GetHUDIcon(inv->GetClass()); if (!AltIcon.Exists()) return; if (AltIcon.isValid()) { icon = AltIcon; } else if (inv->SpawnState && inv->SpawnState->sprite!=0) { FState * state = inv->SpawnState; if (state && (unsigned)state->sprite < (unsigned)sprites.Size ()) { spritedef_t * sprdef = &sprites[state->sprite]; spriteframe_t * sprframe = &SpriteFrames[sprdef->spriteframes + state->GetFrame()]; icon = sprframe->Texture[0]; } } if (icon.isNull()) icon = inv->Icon; if (icon.isValid()) { x -= 9; DrawImageToBox(TexMan[icon], x, y, 8, 10); c++; if (c>=10) { x=xo; y-=11; c=0; } } }
//========================================================================== //*** // DoActionSpecials // handles action specials as code pointers // //========================================================================== bool DoActionSpecials(FScanner &sc, FState & state, Baggage &bag) { int i; int min_args, max_args; FString specname = sc.String; int special = P_FindLineSpecial(sc.String, &min_args, &max_args); if (special > 0 && min_args >= 0) { int paramindex=PrepareStateParameters(&state, 6, bag.Info->Class); StateParams.Set(paramindex, new FxConstant(special, sc)); // Make this consistent with all other parameter parsing if (sc.CheckToken('(')) { for (i = 0; i < 5;) { StateParams.Set(paramindex+i+1, ParseExpression (sc, bag.Info->Class)); i++; if (!sc.CheckToken (',')) break; } sc.MustGetToken (')'); } else i=0; if (i < min_args) { sc.ScriptError ("Too few arguments to %s", specname.GetChars()); } if (i > max_args) { sc.ScriptError ("Too many arguments to %s", specname.GetChars()); } state.SetAction(FindGlobalActionFunction("A_CallSpecial"), false); return true; } return false; }
void gl_RenderFrameModels( const FSpriteModelFrame *smf, const FState *curState, const int curTics, const PClass *ti, Matrix3x4 *normaltransform, int translation) { // [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. FSpriteModelFrame * smfNext = nullptr; double inter = 0.; if( gl_interpolate_model_frames && !(smf->flags & MDL_NOINTERPOLATION) ) { FState *nextState = curState->GetNextState( ); if( curState != nextState && nextState ) { // [BB] To interpolate at more than 35 fps we take tic fractions into account. float ticFraction = 0.; // [BB] In case the tic counter is frozen we have to leave ticFraction at zero. if ( ConsoleState == c_up && menuactive != MENU_On && !(level.flags2 & LEVEL2_FROZEN) ) { float time = GetTimeFloat(); ticFraction = (time - static_cast<int>(time)); } inter = static_cast<double>(curState->Tics - curTics - ticFraction)/static_cast<double>(curState->Tics); // [BB] For some actors (e.g. ZPoisonShroom) spr->actor->tics can be bigger than curState->Tics. // In this case inter is negative and we need to set it to zero. if ( inter < 0. ) inter = 0.; else { // [BB] Workaround for actors that use the same frame twice in a row. // Most of the standard Doom monsters do this in their see state. if ( (smf->flags & MDL_INTERPOLATEDOUBLEDFRAMES) ) { const FState *prevState = curState - 1; if ( (curState->sprite == prevState->sprite) && ( curState->Frame == prevState->Frame) ) { inter /= 2.; inter += 0.5; } if ( (curState->sprite == nextState->sprite) && ( curState->Frame == nextState->Frame) ) { inter /= 2.; nextState = nextState->GetNextState( ); } } if ( inter != 0.0 ) smfNext = gl_FindModelFrame(ti, nextState->sprite, nextState->Frame, false); } } } for(int i=0; i<MAX_MODELS_PER_FRAME; i++) { if (smf->modelIDs[i] != -1) { FModel * mdl = Models[smf->modelIDs[i]]; FTexture *tex = smf->skinIDs[i].isValid()? TexMan(smf->skinIDs[i]) : nullptr; mdl->BuildVertexBuffer(); gl_RenderState.SetVertexBuffer(mdl->mVBuf); mdl->PushSpriteMDLFrame(smf, i); if ( smfNext && smf->modelframes[i] != smfNext->modelframes[i] ) mdl->RenderFrame(tex, smf->modelframes[i], smfNext->modelframes[i], inter, translation); else mdl->RenderFrame(tex, smf->modelframes[i], smf->modelframes[i], 0.f, translation); gl_RenderState.SetVertexBuffer(GLRenderer->mVBO); } } }
//========================================================================== //*** // ParseStates // parses a state block // //========================================================================== void ParseStates(FScanner &sc, FActorInfo * actor, AActor * defaults, Baggage &bag) { FString statestring; FState state; char lastsprite[5]=""; sc.MustGetStringName ("{"); sc.SetEscape(false); // disable escape sequences in the state parser while (!sc.CheckString ("}") && !sc.End) { memset(&state,0,sizeof(state)); statestring = ParseStateString(sc); if (!statestring.CompareNoCase("GOTO")) { do_goto: statestring = ParseStateString(sc); if (sc.CheckString ("+")) { sc.MustGetNumber (); statestring += '+'; statestring += sc.String; } if (!bag.statedef.SetGotoLabel(statestring)) { sc.ScriptError("GOTO before first state"); } } else if (!statestring.CompareNoCase("STOP")) { do_stop: if (!bag.statedef.SetStop()) { sc.ScriptError("STOP before first state"); continue; } } else if (!statestring.CompareNoCase("WAIT") || !statestring.CompareNoCase("FAIL")) { if (!bag.statedef.SetWait()) { sc.ScriptError("%s before first state", sc.String); continue; } } else if (!statestring.CompareNoCase("LOOP")) { if (!bag.statedef.SetLoop()) { sc.ScriptError("LOOP before first state"); continue; } } else { sc.MustGetString(); if (sc.Compare (":")) { do { bag.statedef.AddStateLabel(statestring); statestring = ParseStateString(sc); if (!statestring.CompareNoCase("GOTO")) { goto do_goto; } else if (!statestring.CompareNoCase("STOP")) { goto do_stop; } sc.MustGetString (); } while (sc.Compare (":")); // continue; } sc.UnGet (); if (statestring.Len() != 4) { sc.ScriptError ("Sprite names must be exactly 4 characters\n"); } state.sprite = GetSpriteIndex(statestring); state.Misc1 = state.Misc2 = 0; state.ParameterIndex = 0; sc.MustGetString(); statestring = sc.String; if (sc.CheckString("RANDOM")) { int min, max; sc.MustGetStringName("("); sc.MustGetNumber(); min = clamp<int>(sc.Number, -1, SHRT_MAX); sc.MustGetStringName(","); sc.MustGetNumber(); max = clamp<int>(sc.Number, -1, SHRT_MAX); sc.MustGetStringName(")"); if (min > max) { swapvalues(min, max); } state.Tics = min; state.TicRange = max - min; } else { sc.MustGetNumber(); state.Tics = clamp<int>(sc.Number, -1, SHRT_MAX); state.TicRange = 0; } while (sc.GetString() && !sc.Crossed) { if (sc.Compare("BRIGHT")) { state.Fullbright = true; continue; } if (sc.Compare("FAST")) { state.Fast = true; continue; } if (sc.Compare("SLOW")) { state.Slow = true; continue; } if (sc.Compare("NODELAY")) { if (bag.statedef.GetStateLabelIndex(NAME_Spawn) == bag.statedef.GetStateCount()) { state.NoDelay = true; } else { sc.ScriptMessage("NODELAY may only be used immediately after Spawn:"); } continue; } if (sc.Compare("OFFSET")) { // specify a weapon offset sc.MustGetStringName("("); sc.MustGetNumber(); state.Misc1 = sc.Number; sc.MustGetStringName (","); sc.MustGetNumber(); state.Misc2 = sc.Number; sc.MustGetStringName(")"); continue; } if (sc.Compare("LIGHT")) { sc.MustGetStringName("("); do { sc.MustGetString(); #ifdef DYNLIGHT AddStateLight(&state, sc.String); #endif } while (sc.CheckString(",")); sc.MustGetStringName(")"); continue; } if (sc.Compare("CANRAISE")) { state.CanRaise = true; continue; } // Make the action name lowercase strlwr (sc.String); if (DoActionSpecials(sc, state, bag)) { goto endofstate; } FName funcname = FName(sc.String, true); PSymbol *sym = bag.Info->Class->Symbols.FindSymbol (funcname, true); if (sym != NULL && sym->SymbolType == SYM_ActionFunction) { PSymbolActionFunction *afd = static_cast<PSymbolActionFunction *>(sym); state.SetAction(afd, false); if (!afd->Arguments.IsEmpty()) { const char *params = afd->Arguments.GetChars(); int numparams = (int)afd->Arguments.Len(); int v; if (!islower(*params)) { sc.MustGetStringName("("); } else { if (!sc.CheckString("(")) { state.ParameterIndex = afd->defaultparameterindex+1; goto endofstate; } } int paramindex = PrepareStateParameters(&state, numparams, bag.Info->Class); int paramstart = paramindex; bool varargs = params[numparams - 1] == '+'; int varargcount = 0; if (varargs) { paramindex++; } else if (afd->defaultparameterindex > -1) { StateParams.Copy(paramindex, afd->defaultparameterindex, int(afd->Arguments.Len())); } while (*params) { FxExpression *x; if ((*params == 'l' || *params == 'L') && sc.CheckNumber()) { // Special case: State label as an offset if (sc.Number > 0 && statestring.Len() > 1) { sc.ScriptError("You cannot use state jumps commands with a jump offset on multistate definitions\n"); } v=sc.Number; if (v<0) { sc.ScriptError("Negative jump offsets are not allowed"); } if (v > 0) { x = new FxStateByIndex(bag.statedef.GetStateCount() + v, sc); } else { x = new FxConstant((FState*)NULL, sc); } } else { // Use the generic parameter parser for everything else x = ParseParameter(sc, bag.Info->Class, *params, false); } StateParams.Set(paramindex++, x); params++; if (varargs) { varargcount++; } if (*params) { if (*params == '+') { if (sc.CheckString(")")) { StateParams.Set(paramstart, new FxConstant(varargcount, sc)); goto endofstate; } params--; StateParams.Reserve(1, bag.Info->Class); } else if ((islower(*params) || *params=='!') && sc.CheckString(")")) { goto endofstate; } sc.MustGetStringName (","); } } sc.MustGetStringName(")"); } else { sc.MustGetString(); if (sc.Compare("(")) { sc.ScriptError("You cannot pass parameters to '%s'\n", funcname.GetChars()); } sc.UnGet(); } goto endofstate; } sc.ScriptError("Invalid state parameter %s\n", sc.String); } sc.UnGet(); endofstate: if (!bag.statedef.AddStates(&state, statestring)) { sc.ScriptError ("Invalid frame character string '%s'", statestring.GetChars()); } } } sc.SetEscape(true); // re-enable escape sequences }