bool P_MorphedDeath(AActor *actor, AActor **morphed, int *morphedstyle, int *morphedhealth) { // May be a morphed player if ((actor->player) && (actor->player->morphTics) && (actor->player->MorphStyle & MORPH_UNDOBYDEATH) && (actor->player->mo) && (actor->player->mo->tracer)) { AActor *realme = actor->player->mo->tracer; int realstyle = actor->player->MorphStyle; int realhealth = actor->health; if (P_UndoPlayerMorph(actor->player, actor->player, !!(actor->player->MorphStyle & MORPH_UNDOBYDEATHFORCED))) { *morphed = realme; *morphedstyle = realstyle; *morphedhealth = realhealth; return true; } return false; } // May be a morphed monster if (actor->GetClass()->IsDescendantOf(RUNTIME_CLASS(AMorphedMonster))) { AMorphedMonster *fakeme = static_cast<AMorphedMonster *>(actor); AActor *realme = fakeme->UnmorphedMe; if (realme != NULL) { if ((fakeme->UnmorphTime) && (fakeme->MorphStyle & MORPH_UNDOBYDEATH)) { int realstyle = fakeme->MorphStyle; int realhealth = fakeme->health; if (P_UndoMonsterMorph(fakeme, !!(fakeme->MorphStyle & MORPH_UNDOBYDEATHFORCED))) { *morphed = realme; *morphedstyle = realstyle; *morphedhealth = realhealth; return true; } } if (realme->flags4 & MF4_BOSSDEATH) { realme->health = 0; // make sure that A_BossDeath considers it dead. // FIXME: Use the caller's stack once the whole chain is scriptable. VMFrameStack stack; VMValue params[3] = { realme, realme, VMValue(NULL, ATAG_STATE) }; stack.Call(A_BossDeath_VMPtr, params, countof(params), NULL, 0, NULL); } } fakeme->flags3 |= MF3_STAYMORPHED; // moved here from AMorphedMonster::Die() return false; } // Not a morphed player or monster return false; }
bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info, FState **stateret) { if (ActionFunc != NULL) { ActionCycles.Clock(); static VMFrameStack stack; VMValue params[3] = { self, stateowner, VMValue(info, ATAG_STATEINFO) }; // If the function returns a state, store it at *stateret. // If it doesn't return a state but stateret is non-NULL, we need // to set *stateret to NULL. if (stateret != NULL) { *stateret = NULL; if (ActionFunc->Proto == NULL || ActionFunc->Proto->ReturnTypes.Size() == 0 || ActionFunc->Proto->ReturnTypes[0] != TypeState) { stateret = NULL; } } if (stateret == NULL) { stack.Call(ActionFunc, params, countof(params), NULL, 0, NULL); } else { VMReturn ret; ret.PointerAt((void **)stateret); stack.Call(ActionFunc, params, countof(params), &ret, 1, NULL); } ActionCycles.Unclock(); return true; } else { return false; } }