Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
	}
}