EventListenerManager::Listener*
EventListenerManager::SetEventHandlerInternal(
                        JS::Handle<JSObject*> aScopeObject,
                        nsIAtom* aName,
                        const nsAString& aTypeString,
                        const nsEventHandler& aHandler,
                        bool aPermitUntrustedEvents)
{
  MOZ_ASSERT(aScopeObject || aHandler.HasEventHandler(),
             "Must have one or the other!");
  MOZ_ASSERT(aName || !aTypeString.IsEmpty());

  uint32_t eventType = nsContentUtils::GetEventId(aName);
  Listener* listener = FindEventHandler(eventType, aName, aTypeString);

  if (!listener) {
    // If we didn't find a script listener or no listeners existed
    // create and add a new one.
    EventListenerFlags flags;
    flags.mListenerIsJSListener = true;

    nsCOMPtr<nsIJSEventListener> jsListener;
    NS_NewJSEventListener(aScopeObject, mTarget, aName,
                          aHandler, getter_AddRefs(jsListener));
    EventListenerHolder listenerHolder(jsListener);
    AddEventListenerInternal(listenerHolder, eventType, aName, aTypeString,
                             flags, true);

    listener = FindEventHandler(eventType, aName, aTypeString);
  } else {
    nsIJSEventListener* jsListener = listener->GetJSListener();
    MOZ_ASSERT(jsListener,
               "How can we have an event handler with no nsIJSEventListener?");

    bool same = jsListener->GetHandler() == aHandler;
    // Possibly the same listener, but update still the context and scope.
    jsListener->SetHandler(aHandler, aScopeObject);
    if (mTarget && !same && aName) {
      mTarget->EventListenerRemoved(aName);
      mTarget->EventListenerAdded(aName);
    }
  }

  // Set flag to indicate possible need for compilation later
  listener->mHandlerIsString = !aHandler.HasEventHandler();
  if (aPermitUntrustedEvents) {
    listener->mFlags.mAllowUntrustedEvents = true;
  }

  return listener;
}
Beispiel #2
0
ICCItem *CMission::FireOnReward (ICCItem *pData)

//	FireOnReward
//
//	Fire <OnReward>
//
//	Callers are responsible for discarding the result, if not NULL.

	{
	SEventHandlerDesc Event;

	if (FindEventHandler(EVENT_ON_REWARD, &Event))
		{
		CCodeChainCtx Ctx;

		Ctx.SaveAndDefineSourceVar(this);
		Ctx.SaveAndDefineDataVar(pData);

		ICCItem *pResult = Ctx.Run(Event);
		if (pResult->IsError())
			{
			ReportEventError(EVENT_ON_REWARD, pResult);
			Ctx.Discard(pResult);
			return NULL;
			}

		return pResult;
		}

	return NULL;
	}
Beispiel #3
0
ICCItem *CMission::FireOnDeclined (void)

//	FireOnDeclined
//
//	Fire <OnDeclined>. We return the result of the event, which might contain
//	instructions for the mission screen.
//
//	Callers are responsible for discarding the result, if not NULL.

	{
	SEventHandlerDesc Event;

	if (FindEventHandler(EVENT_ON_DECLINED, &Event))
		{
		CCodeChainCtx Ctx;

		Ctx.SaveAndDefineSourceVar(this);

		ICCItem *pResult = Ctx.Run(Event);
		if (pResult->IsError())
			{
			ReportEventError(EVENT_ON_DECLINED, pResult);
			Ctx.Discard(pResult);
			return NULL;
			}

		return pResult;
		}

	return NULL;
	}
Beispiel #4
0
Variant DynamicObject::m_RemoveEventHandler(int numargs, Variant args[])
{
    EventHandler *handler = FindEventHandler(args[0]);
    if (handler) {
        UnregisterEventHandler(handler);
        handler->DecRef();
    }
    return VARNULL;
}
bool CWeaponFireDesc::FireOnDamageOverlay (SDamageCtx &Ctx, CEnergyField *pOverlay)

//	FireOnDamageOverlay
//
//	Fire OnDamageOverlay event. Returns TRUE if we should skip further overlay damage

	{
	SEventHandlerDesc Event;
	if (FindEventHandler(evtOnDamageOverlay, &Event))
		{
		//	Setup arguments

		CCodeChainCtx CCCtx;

		CCCtx.SaveAndDefineSourceVar(Ctx.pObj);
		CCCtx.DefineInteger(CONSTLIT("aArmorSeg"), Ctx.iSectHit);
		CCCtx.DefineInteger(CONSTLIT("aOverlayID"), pOverlay->GetID());
		CCCtx.DefineSpaceObject(CONSTLIT("aCause"), Ctx.pCause);
		CCCtx.DefineSpaceObject(CONSTLIT("aAttacker"), Ctx.Attacker.GetObj());
		CCCtx.DefineSpaceObject(CONSTLIT("aOrderGiver"), (Ctx.Attacker.GetObj() ? Ctx.Attacker.GetObj()->GetOrderGiver(Ctx.Attacker.GetCause()) : NULL));
		CCCtx.DefineVector(CONSTLIT("aHitPos"), Ctx.vHitPos);
		CCCtx.DefineInteger(CONSTLIT("aHitDir"), Ctx.iDirection);
		CCCtx.DefineInteger(CONSTLIT("aDamageHP"), Ctx.iDamage);
		CCCtx.DefineString(CONSTLIT("aDamageType"), GetDamageShortName(Ctx.Damage.GetDamageType()));
		CCCtx.DefineItemType(CONSTLIT("aWeaponType"), Ctx.pDesc->GetWeaponType());

		ICCItem *pResult = CCCtx.Run(Event);
		if (pResult->IsError())
			Ctx.pObj->ReportEventError(ON_DAMAGE_OVERLAY_EVENT, pResult);

		//	If we return Nil, then we continue processing

		bool bResult;
		if (pResult->IsNil())
			bResult = false;

		//	Otherwise, the result is the damage left

		else
			{
			Ctx.iDamage = pResult->GetIntegerValue();
			bResult = true;
			}

		CCCtx.Discard(pResult);

		return bResult;
		}
	else
		return false;
	}
bool CWeaponFireDesc::FireOnFragment (const CDamageSource &Source, CSpaceObject *pShot, const CVector &vHitPos, CSpaceObject *pNearestObj, CSpaceObject *pTarget)

//	FireOnFragment
//
//	Event fires when a shot fragments. If we return TRUE then we skip the default
//	fragmentation event.

	{
	SEventHandlerDesc Event;
	if (FindEventHandler(evtOnFragment, &Event))
		{
		//	Setup arguments

		CCodeChainCtx CCCtx;

		CCCtx.SaveAndDefineSourceVar(pShot);
		CCCtx.DefineSpaceObject(CONSTLIT("aNearestObj"), pNearestObj);
		CCCtx.DefineSpaceObject(CONSTLIT("aTargetObj"), pTarget);
		CCCtx.DefineVector(CONSTLIT("aHitPos"), vHitPos);
		CCCtx.DefineInteger(CONSTLIT("aHitDir"), (pShot ? pShot->GetRotation() : 0));
		CCCtx.DefineItemType(CONSTLIT("aWeaponType"), GetWeaponType());
		CCCtx.DefineString(CONSTLIT("aWeaponFragment"), m_sUNID);

		CSpaceObject *pAttacker = Source.GetObj();
		CCCtx.DefineSpaceObject(CONSTLIT("aCause"), pShot);
		CCCtx.DefineSpaceObject(CONSTLIT("aAttacker"), pAttacker);
		CCCtx.DefineSpaceObject(CONSTLIT("aOrderGiver"), (pAttacker ? pAttacker->GetOrderGiver(Source.GetCause()) : NULL));

		ICCItem *pResult = CCCtx.Run(Event);
		if (pResult->IsError())
			pShot->ReportEventError(ON_FRAGMENT_EVENT, pResult);

		//	If we return Nil, then we continue processing

		bool bResult;
		if (pResult->IsNil())
			bResult = false;

		//	Otherwise, we skip fragmentation

		else
			bResult = true;

		CCCtx.Discard(pResult);

		return bResult;
		}
	else
		return false;
	}
Beispiel #7
0
int DynamicObject::FireEvent(const char *event)
{
    int rc = 0;
    EventHandler *handler = FindEventHandler(event);
    if (handler) {
        Tls *tls = tlsGet();
        tls->object = this;
        lmbox_free(tls->event);
        tls->event = strdup(event);
        systemObject->Log(3, "Executing event handler %s for event %s in %s (run=%d)", handler->GetName(), event, name, systemObject->IsRunning());
        rc = handler->Fire();
        systemObject->Log(5, "Result is %d in %s from event handler %s for event %s", rc, name, handler->GetName(), event);
        handler->DecRef();
        lmbox_destroy((void**)&tls->event);
    }
    return rc;
}
void Object::UnsubscribeFromEvent(StringHash eventType)
{
    for (;;)
    {
        EventHandler* previous;
        EventHandler* handler = FindEventHandler(eventType, &previous);
        if (handler)
        {
            if (handler->GetSender())
                context_->RemoveEventReceiver(this, handler->GetSender(), eventType);
            else
                context_->RemoveEventReceiver(this, eventType);
            eventHandlers_.Erase(handler, previous);
        }
        else
            break;
    }
}
void
EventListenerManager::RemoveEventHandler(nsIAtom* aName,
                                         const nsAString& aTypeString)
{
  if (mClearingListeners) {
    return;
  }

  uint32_t eventType = nsContentUtils::GetEventId(aName);
  Listener* listener = FindEventHandler(eventType, aName, aTypeString);

  if (listener) {
    mListeners.RemoveElementAt(uint32_t(listener - &mListeners.ElementAt(0)));
    mNoListenerForEvent = NS_EVENT_NULL;
    mNoListenerForEventAtom = nullptr;
    if (mTarget && aName) {
      mTarget->EventListenerRemoved(aName);
    }
  }
}
const TypedEventHandler*
EventListenerManager::GetTypedEventHandler(nsIAtom* aEventName,
                                           const nsAString& aTypeString)
{
  uint32_t eventType = nsContentUtils::GetEventId(aEventName);
  Listener* listener = FindEventHandler(eventType, aEventName, aTypeString);

  if (!listener) {
    return nullptr;
  }

  JSEventHandler* jsEventHandler = listener->GetJSEventHandler();

  if (listener->mHandlerIsString) {
    CompileEventHandlerInternal(listener, nullptr, nullptr);
  }

  const TypedEventHandler& typedHandler =
    jsEventHandler->GetTypedEventHandler();
  return typedHandler.HasEventHandler() ? &typedHandler : nullptr;
}
void CAdventureDesc::FireOnGameStart (void)

//	FireOnGameStart
//
//	Fire OnGameStart event

{
    SEventHandlerDesc Event;

    if (FindEventHandler(ON_GAME_START_EVENT, &Event))
    {
        CCodeChainCtx Ctx;

        //	Run code

        ICCItem *pResult = Ctx.Run(Event);
        if (pResult->IsError())
            kernelDebugLogMessage("OnGameStart error: %s", pResult->GetStringValue());
        Ctx.Discard(pResult);
    }
}
Beispiel #12
0
void CMission::FireOnStart (void)

//	FireOnStart
//
//	Fire <OnStarted>

{
    SEventHandlerDesc Event;

    if (FindEventHandler(EVENT_ON_STARTED, &Event))
    {
        CCodeChainCtx Ctx;

        Ctx.SaveAndDefineSourceVar(this);

        ICCItem *pResult = Ctx.Run(Event);
        if (pResult->IsError())
            ReportEventError(EVENT_ON_STARTED, pResult);
        Ctx.Discard(pResult);
    }
}
Beispiel #13
0
void CMission::FireOnSetPlayerTarget (const CString &sReason)

//	FireOnSetPlayerTarget
//
//	Fire <OnSetPlayerTarget>

{
    SEventHandlerDesc Event;

    if (FindEventHandler(EVENT_ON_SET_PLAYER_TARGET, &Event))
    {
        CCodeChainCtx Ctx;

        Ctx.SaveAndDefineSourceVar(this);
        Ctx.DefineString(STR_A_REASON, sReason);

        ICCItem *pResult = Ctx.Run(Event);
        if (pResult->IsError())
            ReportEventError(EVENT_ON_SET_PLAYER_TARGET, pResult);
        Ctx.Discard(pResult);
    }
}
Beispiel #14
0
void CMission::FireCustomEvent (const CString &sEvent)

//	FireCustomEvent
//
//	Fires a custom timed event

{
    SEventHandlerDesc Event;

    if (FindEventHandler(sEvent, &Event))
    {
        CCodeChainCtx Ctx;

        Ctx.SetEvent(eventDoEvent);
        Ctx.SaveAndDefineSourceVar(this);

        ICCItem *pResult = Ctx.Run(Event);
        if (pResult->IsError())
            ReportEventError(sEvent, pResult);
        Ctx.Discard(pResult);
    }
}
Beispiel #15
0
void CMission::FireOnReward (ICCItem *pData)

//	FireOnReward
//
//	Fire <OnReward>

{
    SEventHandlerDesc Event;

    if (FindEventHandler(EVENT_ON_REWARD, &Event))
    {
        CCodeChainCtx Ctx;

        Ctx.SaveAndDefineSourceVar(this);
        Ctx.SaveAndDefineDataVar(pData);

        ICCItem *pResult = Ctx.Run(Event);
        if (pResult->IsError())
            ReportEventError(EVENT_ON_REWARD, pResult);
        Ctx.Discard(pResult);
    }
}
void CAdventureDesc::FireOnGameEnd (const CGameRecord &Game, const SBasicGameStats &BasicStats)

//	FireOnGameEnd
//
//	Fire OnGameEnd event

{
    SEventHandlerDesc Event;

    if (FindEventHandler(ON_GAME_END_EVENT, &Event))
    {
        CCodeChainCtx Ctx;

        //	Initialize variables

        Ctx.DefineInteger(CONSTLIT("aScore"), Game.GetScore());
        Ctx.DefineInteger(CONSTLIT("aResurrectCount"), Game.GetResurrectCount());
        Ctx.DefineInteger(CONSTLIT("aSystemsVisited"), BasicStats.iSystemsVisited);
        Ctx.DefineInteger(CONSTLIT("aEnemiesDestroyed"), BasicStats.iEnemiesDestroyed);
        Ctx.DefineInteger(CONSTLIT("aBestEnemiesDestroyed"), BasicStats.iBestEnemyDestroyedCount);
        if (BasicStats.dwBestEnemyDestroyed)
            Ctx.DefineInteger(CONSTLIT("aBestEnemyClass"), BasicStats.dwBestEnemyDestroyed);
        else
            Ctx.DefineNil(CONSTLIT("aBestEnemyClass"));

        Ctx.DefineString(CONSTLIT("aEndGameReason"), Game.GetEndGameReason());
        Ctx.DefineString(CONSTLIT("aEpitaph"), Game.GetEndGameEpitaph());
        Ctx.DefineString(CONSTLIT("aEpitaphOriginal"), Game.GetEndGameEpitaph());
        Ctx.DefineString(CONSTLIT("aTime"), Game.GetPlayTimeString());

        //	Invoke

        ICCItem *pResult = Ctx.Run(Event);
        if (pResult->IsError())
            kernelDebugLogMessage("OnGameEnd error: %s", pResult->GetStringValue());
        Ctx.Discard(pResult);
    }
}
Beispiel #17
0
void CMission::FireOnStop (const CString &sReason, ICCItem *pData)

//	FireOnStop
//
//	Fire <OnCompleted>

{
    SEventHandlerDesc Event;

    if (FindEventHandler(EVENT_ON_COMPLETED, &Event))
    {
        CCodeChainCtx Ctx;

        Ctx.SaveAndDefineSourceVar(this);
        Ctx.SaveAndDefineDataVar(pData);
        Ctx.DefineString(STR_A_REASON, sReason);

        ICCItem *pResult = Ctx.Run(Event);
        if (pResult->IsError())
            ReportEventError(EVENT_ON_COMPLETED, pResult);
        Ctx.Discard(pResult);
    }
}
bool CWeaponFireDesc::FireOnDamageShields (SDamageCtx &Ctx, int iDevice)

//	FireOnDamageShields
//
//	Fire OnDamageShields event. Returns TRUE if we should skip further shields damage

	{
	SEventHandlerDesc Event;
	if (FindEventHandler(evtOnDamageShields, &Event))
		{
		//	Setup arguments

		CCodeChainCtx CCCtx;

		CItemListManipulator ItemList(Ctx.pObj->GetItemList());
		CShip *pShip = Ctx.pObj->AsShip();
		if (pShip)
			pShip->SetCursorAtDevice(ItemList, iDevice);

		CCCtx.SaveAndDefineSourceVar(Ctx.pObj);
		CCCtx.DefineInteger(CONSTLIT("aArmorSeg"), Ctx.iSectHit);
		CCCtx.DefineInteger(CONSTLIT("aDevice"), iDevice);
		CCCtx.DefineItem(CONSTLIT("aDeviceItem"), ItemList.GetItemAtCursor());
		CCCtx.DefineSpaceObject(CONSTLIT("aCause"), Ctx.pCause);
		CCCtx.DefineSpaceObject(CONSTLIT("aAttacker"), Ctx.Attacker.GetObj());
		CCCtx.DefineSpaceObject(CONSTLIT("aOrderGiver"), (Ctx.Attacker.GetObj() ? Ctx.Attacker.GetObj()->GetOrderGiver(Ctx.Attacker.GetCause()) : NULL));
		CCCtx.DefineVector(CONSTLIT("aHitPos"), Ctx.vHitPos);
		CCCtx.DefineInteger(CONSTLIT("aHitDir"), Ctx.iDirection);
		CCCtx.DefineInteger(CONSTLIT("aDamageHP"), Ctx.iDamage);
		CCCtx.DefineString(CONSTLIT("aDamageType"), GetDamageShortName(Ctx.Damage.GetDamageType()));
		CCCtx.DefineItemType(CONSTLIT("aWeaponType"), Ctx.pDesc->GetWeaponType());

		CCCtx.DefineInteger(CONSTLIT("aShieldHP"), Ctx.iHPLeft);
		CCCtx.DefineInteger(CONSTLIT("aShieldDamageHP"), Ctx.iShieldDamage);
		CCCtx.DefineInteger(CONSTLIT("aArmorDamageHP"), Ctx.iDamage - Ctx.iAbsorb);
		if (Ctx.bReflect)
			{
			CCCtx.DefineString(CONSTLIT("aShieldReflect"), STR_SHIELD_REFLECT);
			CCCtx.DefineInteger(CONSTLIT("aOriginalShieldDamageHP"), Ctx.iOriginalShieldDamage);
			CCCtx.DefineInteger(CONSTLIT("aOriginalArmorDamageHP"), Ctx.iDamage - Ctx.iOriginalAbsorb);
			}
		else
			{
			CCCtx.DefineNil(CONSTLIT("aShieldReflect"));
			CCCtx.DefineInteger(CONSTLIT("aOriginalShieldDamageHP"), Ctx.iShieldDamage);
			CCCtx.DefineInteger(CONSTLIT("aOriginalArmorDamageHP"), Ctx.iDamage - Ctx.iAbsorb);
			}

		ICCItem *pResult = CCCtx.Run(Event);

		//	If we return Nil, then we continue processing

		bool bResult;
		if (pResult->IsNil())
			bResult = false;

		//	If this is an integer, we pass damage to armor

		else if (pResult->IsInteger())
			{
			Ctx.iDamage = pResult->GetIntegerValue();
			bResult = true;
			}

		//	If we return a list, then modify variables

		else if (pResult->IsList())
			{
			//	A single value means we modified the damage to armor

			if (pResult->GetCount() == 1)
				{
				if (strEquals(pResult->GetElement(0)->GetStringValue(), STR_SHIELD_REFLECT))
					{
					Ctx.bReflect = true;
					Ctx.iAbsorb = Ctx.iDamage;
					Ctx.iShieldDamage = 0;
					}
				else
					{
					Ctx.iShieldDamage = Max(0, Min(pResult->GetElement(0)->GetIntegerValue(), Ctx.iHPLeft));
					if (Ctx.bReflect)
						{
						Ctx.bReflect = false;
						Ctx.iAbsorb = Ctx.iOriginalAbsorb;
						}
					}
				}

			//	Two values mean we modified both damage to armor and shield damage

			else if (pResult->GetCount() == 2)
				{
				Ctx.bReflect = false;
				Ctx.iShieldDamage = Max(0, Min(pResult->GetElement(0)->GetIntegerValue(), Ctx.iHPLeft));
				Ctx.iAbsorb = Max(0, Ctx.iDamage - Max(0, pResult->GetElement(1)->GetIntegerValue()));
				}

			//	Otherwise, we deal with reflection

			else
				{
				Ctx.bReflect = strEquals(pResult->GetElement(0)->GetStringValue(), STR_SHIELD_REFLECT);
				Ctx.iShieldDamage = Max(0, Min(pResult->GetElement(1)->GetIntegerValue(), Ctx.iHPLeft));
				Ctx.iAbsorb = Max(0, Ctx.iDamage - Max(0, pResult->GetElement(2)->GetIntegerValue()));
				}

			//	Proceed with processing

			bResult = false;
			}

		//	If this is the string "reflect" then we reflect

		else if (strEquals(pResult->GetStringValue(), STR_SHIELD_REFLECT))
			{
			Ctx.bReflect = true;
			Ctx.iAbsorb = Ctx.iDamage;
			Ctx.iShieldDamage = 0;
			bResult = false;
			}

		//	Otherwise, error

		else
			{
			Ctx.pObj->ReportEventError(ON_DAMAGE_OVERLAY_EVENT, pResult);
			bResult = true;
			}

		CCCtx.Discard(pResult);

		return bResult;
		}
	else
		return false;
	}
ALERROR CWeaponFireDesc::OnDesignLoadComplete (SDesignLoadCtx &Ctx)

//	OnDesignLoadComplete
//
//	Done loading all design elements

	{
	ALERROR error;
	int i;

	if (error = m_Image.OnDesignLoadComplete(Ctx))
		return error;

	if (error = m_ExhaustImage.OnDesignLoadComplete(Ctx))
		return error;

	if (error = m_pAmmoType.Bind(Ctx))
		return error;

	if (error = m_pEffect.Bind(Ctx))
		return error;

	if (error = m_pHitEffect.Bind(Ctx))
		return error;

	if (error = m_pFireEffect.Bind(Ctx))
		return error;

	if (m_pEnhanced)
		if (error = m_pEnhanced->OnDesignLoadComplete(Ctx))
			return error;

	//	Load some events for efficiency

	for (i = 0; i < evtCount; i++)
		{
		if (!FindEventHandler(CString(CACHED_EVENTS[i], -1, true), &m_CachedEvents[i]))
			{
			m_CachedEvents[i].pExtension = NULL;
			m_CachedEvents[i].pCode = NULL;
			}
		}

	//	If we have an OnFragment event, then we enable proximity blast

	if (HasOnFragmentEvent())
		m_bProximityBlast = true;

	//	Fragment

	SFragmentDesc *pNext = m_pFirstFragment;
	while (pNext)
		{
		if (error = pNext->pDesc->OnDesignLoadComplete(Ctx))
			return error;

		pNext = pNext->pNext;
		}

	return NOERROR;
	}
ALERROR CEnergyFieldType::OnCreateFromXML (SDesignLoadCtx &Ctx, CXMLElement *pDesc)

//	OnCreateFromXML
//
//	Create from XML

	{
	ALERROR error;

	//	Effect

	CXMLElement *pEffect = pDesc->GetContentElementByTag(EFFECT_TAG);
	if (pEffect)
		{
		if (error = CEffectCreator::CreateFromXML(Ctx, 
				pEffect, 
				strPatternSubst(CONSTLIT("%d:e"), GetUNID()), 
				&m_pEffect))
			{
			Ctx.sError = strPatternSubst(CONSTLIT("energy field %x: Unable to load effect"), GetUNID());
			return error;
			}
		}

	pEffect = pDesc->GetContentElementByTag(HIT_EFFECT_TAG);
	if (pEffect == NULL)
		pEffect = pDesc->GetContentElementByTag(EFFECT_WHEN_HIT_TAG);

	if (pEffect)
		{
		if (error = CEffectCreator::CreateFromXML(Ctx, 
				pEffect, 
				strPatternSubst(CONSTLIT("%d:h"), GetUNID()), 
				&m_pHitEffect))
			{
			Ctx.sError = strPatternSubst(CONSTLIT("energy field %x: Unable to load hit effect"), GetUNID());
			return error;
			}

		//	For compatibility with previous versions, if we're using the old
		//	<ShipEnergyFieldType> then altEffect defaults to TRUE. Otherwise, for new
		//	<OverlayType> altEffect defaults to false.

		bool bAltEffect;
		if (pEffect->FindAttributeBool(ALT_EFFECT_ATTRIB, &bAltEffect))
			m_bAltHitEffect = bAltEffect;
		else
			m_bAltHitEffect = strEquals(pDesc->GetTag(), SHIP_ENERGY_FIELD_TYPE_TAG);
		}
	else
		m_bAltHitEffect = false;

	//	Rotation

	m_bRotateWithShip = !pDesc->GetAttributeBool(IGNORE_SHIP_ROTATION_ATTRIB);

	//	Damage adjustment

	LoadDamageAdj(pDesc, ABSORB_ADJ_ATTRIB, m_iAbsorbAdj);

	//	Bonus adjustment

	LoadDamageAdj(pDesc, BONUS_ADJ_ATTRIB, m_iBonusAdj);

	//	Load the weapon suppress

	if (error = m_WeaponSuppress.InitFromXML(pDesc->GetAttribute(WEAPON_SUPPRESS_ATTRIB)))
		{
		Ctx.sError = CONSTLIT("Unable to load weapon suppress attribute");
		return error;
		}

	//	Keep track of the events that we have

	m_bHasOnUpdateEvent = FindEventHandler(ON_UPDATE_EVENT);

	//	Done

	return NOERROR;
	}
bool Object::HasSubscribedToEvent(StringHash eventType) const
{
    return FindEventHandler(eventType) != 0;
}
Beispiel #22
0
ALERROR COverlayType::OnCreateFromXML (SDesignLoadCtx &Ctx, CXMLElement *pDesc)

//	OnCreateFromXML
//
//	Create from XML

	{
	ALERROR error;

	//	Effect

	CXMLElement *pEffect = pDesc->GetContentElementByTag(EFFECT_TAG);
	if (pEffect)
		{
		if (error = CEffectCreator::CreateFromXML(Ctx, 
				pEffect, 
				strPatternSubst(CONSTLIT("%d:e"), GetUNID()), 
				&m_pEffect))
			{
			Ctx.sError = strPatternSubst(CONSTLIT("energy field %x: Unable to load effect"), GetUNID());
			return error;
			}
		}

	pEffect = pDesc->GetContentElementByTag(HIT_EFFECT_TAG);
	if (pEffect == NULL)
		pEffect = pDesc->GetContentElementByTag(EFFECT_WHEN_HIT_TAG);

	if (pEffect)
		{
		if (error = CEffectCreator::CreateFromXML(Ctx, 
				pEffect, 
				strPatternSubst(CONSTLIT("%d:h"), GetUNID()), 
				&m_pHitEffect))
			{
			Ctx.sError = strPatternSubst(CONSTLIT("energy field %x: Unable to load hit effect"), GetUNID());
			return error;
			}

		//	For compatibility with previous versions, if we're using the old
		//	<ShipEnergyFieldType> then altEffect defaults to TRUE. Otherwise, for new
		//	<OverlayType> altEffect defaults to false.

		bool bAltEffect;
		if (pEffect->FindAttributeBool(ALT_EFFECT_ATTRIB, &bAltEffect))
			m_fAltHitEffect = bAltEffect;
		else
			m_fAltHitEffect = strEquals(pDesc->GetTag(), SHIP_ENERGY_FIELD_TYPE_TAG);
		}
	else
		m_fAltHitEffect = false;

	//	Rotation

	m_fRotateWithShip = !pDesc->GetAttributeBool(IGNORE_SHIP_ROTATION_ATTRIB);

	//	Damage adjustment

	int iAbsorbCount;
	LoadDamageAdj(pDesc, ABSORB_ADJ_ATTRIB, m_iAbsorbAdj, &iAbsorbCount);

	//	Bonus adjustment

	LoadDamageAdj(pDesc, BONUS_ADJ_ATTRIB, m_iBonusAdj);

	//	Load the weapon suppress

	if (error = m_WeaponSuppress.InitFromXML(pDesc->GetAttribute(WEAPON_SUPPRESS_ATTRIB)))
		{
		Ctx.sError = CONSTLIT("Unable to load weapon suppress attribute");
		return error;
		}

	//	Keep track of the events that we have

	m_fHasOnUpdateEvent = FindEventHandler(ON_UPDATE_EVENT);

	//	Are we a field/shield overlay (or part of hull)?
	//	By default, we are a shield overlay if we absorb damage.

	bool bValue;
	if (pDesc->FindAttributeBool(SHIELD_OVERLAY_ATTRIB, &bValue))
		m_fShieldOverlay = bValue;
	else
		m_fShieldOverlay = (iAbsorbCount > 0);

	//	Counter

	CXMLElement *pCounter = pDesc->GetContentElementByTag(COUNTER_TAG);
	if (pCounter)
		{
		CString sStyle = pCounter->GetAttribute(STYLE_ATTRIB);
		if (strEquals(sStyle, COUNTER_PROGRESS))
			m_iCounterType = counterProgress;
		else if (strEquals(sStyle, COUNTER_RADIUS))
			m_iCounterType = counterRadius;
		else
			{
			Ctx.sError = strPatternSubst(CONSTLIT("Unknown counter style: %s"), sStyle);
			return ERR_FAIL;
			}

		m_sCounterLabel = pCounter->GetAttribute(LABEL_ATTRIB);
		m_iCounterMax = pCounter->GetAttributeIntegerBounded(MAX_ATTRIB, 0, -1, 100);
		m_wCounterColor = ::LoadRGBColor(pCounter->GetAttribute(COLOR_ATTRIB));
		}
	else
		{
		m_iCounterType = counterNone;
		m_iCounterMax = 0;
		m_wCounterColor = 0;
		}

	//	Options

	m_fDisarmShip = pDesc->GetAttributeBool(DISARM_ATTRIB);
	m_fParalyzeShip = pDesc->GetAttributeBool(PARALYZE_ATTRIB);
	m_fDisableShipScreen = pDesc->GetAttributeBool(DISABLE_SHIP_SCREEN_ATTRIB);
	m_fSpinShip = pDesc->GetAttributeBool(SPIN_ATTRIB);

	int iDrag;
	if (pDesc->FindAttributeInteger(DRAG_ATTRIB, &iDrag))
		m_rDrag = Min(Max(0, iDrag), 100) / 100.0;
	else
		m_rDrag = 1.0;

	//	Done

	return NOERROR;
	}