123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518 |
- class ImprovisedExplosive : ExplosivesBase
- {
- protected const float TIME_TRIGGER_INITIAL_DELAY_SECS = 0.1;
- protected const float TIME_TRIGGER_TIMER_BASED_DELAY_SECS = 1.0;
- protected const float TIME_TRIGGER_DELAY_SECS = 0.3;
-
- protected static const string SLOT_TRIGGER_ALARM_CLOCK = "TriggerAlarmClock";
- protected static const string SLOT_TRIGGER_KITCHEN_TIMER = "TriggerKitchenTimer";
- protected static const string SLOT_TRIGGER_REMOTE = "TriggerRemoteDetonator_Receiver";
-
- protected static const string SLOT_EXPLOSIVE_A = "IEDExplosiveA";
- protected static const string SLOT_EXPLOSIVE_B = "IEDExplosiveB";
-
- protected const int SLOT_EXPLOSIVE_COUNT = 2;
- protected const string SLOT_EXPLOSIVES[SLOT_EXPLOSIVE_COUNT] = {
- SLOT_EXPLOSIVE_A,
- SLOT_EXPLOSIVE_B
- };
-
- protected const int SLOT_TRIGGERS_COUNT = 3;
- protected const string SLOT_TRIGGERS[SLOT_TRIGGERS_COUNT] = {
- SLOT_TRIGGER_ALARM_CLOCK,
- SLOT_TRIGGER_KITCHEN_TIMER,
- SLOT_TRIGGER_REMOTE
- };
-
- protected const string ANIM_PHASE_TRIGGER_EMPTY = "TriggerEmpty";
- protected const string ANIM_PHASE_TRIGGER_TIMER = "TriggerTimer";
- protected const string ANIM_PHASE_TRIGGER_CLOCK = "TriggerClock";
- protected const string ANIM_PHASE_TRIGGER_REMOTE = "TriggerRemote";
-
- protected ref RemotelyActivatedItemBehaviour m_RAIB;
-
- void ImprovisedExplosive()
- {
- m_RAIB = new RemotelyActivatedItemBehaviour(this);
- RegisterNetSyncVariableInt("m_RAIB.m_PairDeviceNetIdLow");
- RegisterNetSyncVariableInt("m_RAIB.m_PairDeviceNetIdHigh");
- }
-
- override void EOnInit(IEntity other, int extra)
- {
- if (!g_Game.IsMultiplayer())
- LockTriggerSlots();
- }
- override bool HasLockedTriggerSlots()
- {
- foreach (string triggerSlot : SLOT_TRIGGERS)
- return GetInventory().GetSlotLock(InventorySlots.GetSlotIdFromString(triggerSlot));
-
- return false;
- }
-
- override void LockTriggerSlots()
- {
- foreach (string triggerSlotName : SLOT_TRIGGERS)
- GetInventory().SetSlotLock(InventorySlots.GetSlotIdFromString(triggerSlotName), true);
- }
-
- override void UnlockTriggerSlots()
- {
- foreach (string triggerSlotName : SLOT_TRIGGERS)
- GetInventory().SetSlotLock(InventorySlots.GetSlotIdFromString(triggerSlotName), false);
- }
-
- override void LockExplosivesSlots()
- {
- foreach (string explosiveSlotName : SLOT_EXPLOSIVES)
- GetInventory().SetSlotLock(InventorySlots.GetSlotIdFromString(explosiveSlotName), true);
- }
-
- override void UnlockExplosivesSlots()
- {
- foreach (string explosiveSlotName : SLOT_EXPLOSIVES)
- GetInventory().SetSlotLock(InventorySlots.GetSlotIdFromString(explosiveSlotName), false);
- }
-
- override bool OnStoreLoad(ParamsReadContext ctx, int version)
- {
- if (!super.OnStoreLoad(ctx, version))
- return false;
- if (version <= 134) // up to 1.21
- {
- foreach (string triggerSlotName : SLOT_TRIGGERS)
- {
- int slotId = InventorySlots.GetSlotIdFromString(triggerSlotName);
- bool locked = GetInventory().GetSlotLock(slotId);
- while (locked)
- {
- GetInventory().SetSlotLock(slotId, false);
- locked = GetInventory().GetSlotLock(slotId);
- }
- }
- }
-
- return true;
- }
-
- override void OnStoreSave(ParamsWriteContext ctx)
- {
- super.OnStoreSave(ctx);
-
- LockTriggerSlots();
- }
-
- override void OnVariablesSynchronized()
- {
- super.OnVariablesSynchronized();
-
- if (m_RAIB)
- {
- m_RAIB.OnVariableSynchronized();
- }
-
- foreach (string slotName : SLOT_TRIGGERS)
- {
- EntityAI trigger = GetInventory().FindAttachmentByName(slotName);
- if (trigger)
- {
- UpdateVisuals(trigger);
- break;
- }
- }
- }
-
- override void OnPlacementComplete(Man player, vector position = "0 0 0", vector orientation = "0 0 0")
- {
- super.OnPlacementComplete(player, position, orientation);
-
- if (GetGame().IsServer())
- {
- SetOrientation(vector.Up);
- }
- }
-
- override void EEItemLocationChanged(notnull InventoryLocation oldLoc, notnull InventoryLocation newLoc)
- {
- super.EEItemLocationChanged(oldLoc, newLoc);
- if (m_RAIB)
- {
- m_RAIB.Pair();
- }
- }
-
- override RemotelyActivatedItemBehaviour GetRemotelyActivatedItemBehaviour()
- {
- return m_RAIB;
- }
-
- override void PairRemote(notnull EntityAI trigger)
- {
- m_RAIB.Pair(trigger);
- }
-
- override EntityAI GetPairDevice()
- {
- return m_RAIB.GetPairDevice();
- }
-
- override bool CanBeArmed()
- {
- if (GetArmed())
- return false;
-
- if (!HasLockedTriggerSlots())
- return false;
- foreach (string slotName : SLOT_EXPLOSIVES)
- {
- EntityAI explosive = GetInventory().FindAttachmentByName(slotName);
- if (explosive)
- return true;
- }
-
- return false;
- }
- override bool CanBeDisarmed()
- {
- return true;
- }
-
-
- override bool CanReceiveAttachment(EntityAI attachment, int slotId)
- {
- InventoryLocation il = new InventoryLocation();
- GetInventory().GetCurrentInventoryLocation(il);
-
- foreach (string slotName : SLOT_TRIGGERS)
- {
- if (slotId == InventorySlots.GetSlotIdFromString(slotName))
- {
- if (il.GetType() == InventoryLocationType.HANDS)
- return false;
- }
- }
- return !GetArmed();
- }
-
- override bool CanDisplayAttachmentSlot(int slot_id)
- {
- string slotName = InventorySlots.GetSlotName(slot_id);
- switch (slotName)
- {
- case SLOT_TRIGGER_ALARM_CLOCK:
- case SLOT_TRIGGER_KITCHEN_TIMER:
- case SLOT_TRIGGER_REMOTE:
- return FindAttachmentBySlotName(slotName) != null;
- break;
- }
- return true;
- }
-
- override bool IsTimerDetonable()
- {
- return true;
- }
-
- override bool IsTakeable()
- {
- return !GetArmed() && super.IsTakeable();
- }
-
- override bool IsDeployable()
- {
- return !GetArmed();
- }
-
- override void SetActions()
- {
- super.SetActions();
- AddAction(ActionTogglePlaceObject);
- AddAction(ActionDeployObject);
- }
-
- override void EEHealthLevelChanged(int oldLevel, int newLevel, string zone)
- {
- super.EEHealthLevelChanged(oldLevel, newLevel, zone);
- if (GetGame().IsServer())
- {
- if (newLevel == GameConstants.STATE_RUINED)
- {
- for (int attachmentIdx = 0; attachmentIdx < GetInventory().AttachmentCount(); attachmentIdx++)
- {
- ItemBase attachment = ItemBase.Cast(GetInventory().GetAttachmentFromIndex(attachmentIdx));
- if (attachment)
- {
- attachment.UnlockFromParent();
- attachment.SetHealth("", "", 0.0);
- }
- }
-
- SetArmed(false);
- SetTakeable(true);
- }
- }
- }
-
- override void OnActivatedByItem(notnull ItemBase item)
- {
- if (GetGame().IsServer() && GetArmed())
- {
- bool isTimeTriggered = false;
- array<ItemBase> attachmentsCache = new array<ItemBase>();
- for (int attachmentIdx = 0; attachmentIdx < GetInventory().AttachmentCount(); attachmentIdx++)
- {
- ItemBase attachment = ItemBase.Cast(GetInventory().GetAttachmentFromIndex(attachmentIdx));
- if (attachment)
- attachmentsCache.Insert(attachment);
- }
-
- foreach (ItemBase attachment1 : attachmentsCache)
- attachment1.UnlockFromParent();
-
- //! attachment special handling on disarm
- foreach (ItemBase attachment2 : attachmentsCache)
- {
- if (attachment2.IsInherited(ClockBase))
- {
- isTimeTriggered = true;
- break;
- }
- }
-
- //! go through attached explosives
- foreach (ItemBase attachment3 : attachmentsCache)
- {
- if (attachment3)
- {
- vector dropExtents = "0.5 0.0 0.5";
- if (isTimeTriggered)
- dropExtents[1] = 0.15; //! hard-case blocks shells (result of deferred delete)
- GetInventory().DropEntityInBounds(InventoryMode.SERVER, this, attachment3, dropExtents, 0, 0, 0);
- attachment3.SetAnimationPhase(ANIM_PHASE_VISIBILITY, 1.0);
- attachment3.SetTakeable(false);
- }
- }
-
- float delayFor = TIME_TRIGGER_INITIAL_DELAY_SECS;
- if (isTimeTriggered)
- {
- delayFor = TIME_TRIGGER_INITIAL_DELAY_SECS + TIME_TRIGGER_TIMER_BASED_DELAY_SECS;
- //! defer delete to allow ringing
- GetGame().GetCallQueue(CALL_CATEGORY_SYSTEM).CallLater(DeleteSafe, delayFor * 1000, false);
- }
- else
- {
- DeleteSafe();
- }
- //! final traverse - attached explosives activation
- foreach (ItemBase attachment4 : attachmentsCache)
- {
- if (attachment4.IsAnyInherited({RemoteDetonator, ClockBase}))
- {
- //! defer damage to trigger attachments to allow ringing
- GetGame().GetCallQueue(CALL_CATEGORY_SYSTEM).CallLater(attachment4.DeleteSafe, delayFor * 1000, false);
- }
- if (attachment4 && !attachment4.IsAnyInherited({RemoteDetonator, ClockBase}))
- {
- Param1<ItemBase> params = new Param1<ItemBase>(attachment4);
- GetGame().GetCallQueue(CALL_CATEGORY_SYSTEM).CallLaterByName(attachment4, "OnActivatedByItem", delayFor * 1000, false, params);
- delayFor += TIME_TRIGGER_DELAY_SECS;
- }
- }
- }
- }
-
- //! not exploding itself, rely on attached explosives
- override protected void InitiateExplosion();
-
- override void EEItemAttached(EntityAI item, string slot_name)
- {
- super.EEItemAttached(item, slot_name);
- switch (slot_name)
- {
- case SLOT_TRIGGER_ALARM_CLOCK:
- case SLOT_TRIGGER_KITCHEN_TIMER:
- case SLOT_TRIGGER_REMOTE:
- OnTriggerAttached(FindAttachmentBySlotName(slot_name));
- break;
- }
- }
-
- override void EEItemDetached(EntityAI item, string slot_name)
- {
- super.EEItemDetached(item, slot_name);
- switch (slot_name)
- {
- case SLOT_TRIGGER_ALARM_CLOCK:
- case SLOT_TRIGGER_KITCHEN_TIMER:
- case SLOT_TRIGGER_REMOTE:
- OnTriggerDetached(FindAttachmentBySlotName(slot_name));
- break;
- }
- }
-
- override void OnBeforeDisarm()
- {
- UnlockExplosivesSlots();
- }
-
- override void OnDisarmed(bool pWithTool)
- {
- super.OnDisarmed(pWithTool);
-
- UnpairRemote();
-
- array<ItemBase> attachmentsCache = new array<ItemBase>();
- for (int attachmentIdx = 0; attachmentIdx < GetInventory().AttachmentCount(); attachmentIdx++)
- {
- ItemBase attachment = ItemBase.Cast(GetInventory().GetAttachmentFromIndex(attachmentIdx));
- if (attachment)
- {
- attachmentsCache.Insert(attachment);
- }
- }
-
- foreach (ItemBase attachment1 : attachmentsCache)
- attachment1.UnlockFromParent();
-
- //! attachment special handling on disarm
- foreach (ItemBase attachment2 : attachmentsCache)
- {
- if (attachment2.IsInherited(ClockBase))
- {
- if (pWithTool)
- GetInventory().DropEntity(InventoryMode.SERVER, this, attachment2);
- }
-
- if (attachment2.IsInherited(RemoteDetonator))
- {
- if (pWithTool)
- {
- GetInventory().DropEntity(InventoryMode.SERVER, this, attachment2);
- attachment2.SetHealth("", "", 0.0);
- }
- else
- {
- attachment2.Delete();
- }
- }
- }
-
- LockTriggerSlots();
- SetTakeable(true);
- }
-
- override void UpdateLED(int pState)
- {
- RemoteDetonatorReceiver receiver = RemoteDetonatorReceiver.Cast(FindAttachmentBySlotName(SLOT_TRIGGER_REMOTE));
- if (receiver)
- receiver.UpdateLED(pState, true);
- }
-
- protected void OnTriggerAttached(EntityAI entity)
- {
- UpdateVisuals(entity);
- UpdateLED(ERemoteDetonatorLEDState.LIT);
-
- if (entity.IsInherited(ClockBase))
- Arm();
-
- LockTriggerSlots();
- LockExplosivesSlots();
- }
-
- protected void OnTriggerDetached(EntityAI entity)
- {
- UpdateVisuals(null);
- UpdateLED(ERemoteDetonatorLEDState.OFF);
- }
-
- protected void UpdateVisuals(EntityAI entity)
- {
- if (entity)
- {
- if (entity.IsInherited(RemoteDetonator))
- {
- SetAnimationPhase(ANIM_PHASE_TRIGGER_EMPTY, 1.0);
- SetAnimationPhase(ANIM_PHASE_TRIGGER_TIMER, 1.0);
- SetAnimationPhase(ANIM_PHASE_TRIGGER_CLOCK, 1.0);
- SetAnimationPhase(ANIM_PHASE_TRIGGER_REMOTE, 0.0);
- }
- else if (entity.IsInherited(AlarmClock_ColorBase))
- {
- SetAnimationPhase(ANIM_PHASE_TRIGGER_EMPTY, 1.0);
- SetAnimationPhase(ANIM_PHASE_TRIGGER_TIMER, 1.0);
- SetAnimationPhase(ANIM_PHASE_TRIGGER_CLOCK, 0.0);
- SetAnimationPhase(ANIM_PHASE_TRIGGER_REMOTE, 1.0);
- }
- else if (entity.IsInherited(KitchenTimer))
- {
- SetAnimationPhase(ANIM_PHASE_TRIGGER_EMPTY, 1.0);
- SetAnimationPhase(ANIM_PHASE_TRIGGER_TIMER, 0.0);
- SetAnimationPhase(ANIM_PHASE_TRIGGER_CLOCK, 1.0);
- SetAnimationPhase(ANIM_PHASE_TRIGGER_REMOTE, 1.0);
- }
- }
- else
- {
- SetAnimationPhase(ANIM_PHASE_TRIGGER_EMPTY, 0.0);
- SetAnimationPhase(ANIM_PHASE_TRIGGER_TIMER, 1.0);
- SetAnimationPhase(ANIM_PHASE_TRIGGER_CLOCK, 1.0);
- SetAnimationPhase(ANIM_PHASE_TRIGGER_REMOTE, 1.0);
- }
- }
-
- override string GetDeploySoundset()
- {
- return "placeImprovisedExplosive_SoundSet";
- }
-
- override string GetLoopDeploySoundset()
- {
- return "improvisedexplosive_deploy_SoundSet";
- }
-
- override string GetArmSoundset()
- {
- return "improvisedexplosive_deploy_SoundSet";
- }
-
- override string GetDisarmSoundset()
- {
- return "ImprovisedExplosive_disarm_SoundSet";
- }
-
-
- #ifdef DEVELOPER
- override protected string GetDebugText()
- {
- string debug_output;
- debug_output += string.Format("low net id: %1\n", m_RAIB.GetPairDeviceNetIdLow());
- debug_output += string.Format("high net id: %1\n", m_RAIB.GetPairDeviceNetIdHigh());
- debug_output += string.Format("pair device: %1\n", m_RAIB.GetPairDevice());
- return debug_output;
- }
- #endif
- }
- class ImprovisedExplosivePlacing : ImprovisedExplosive {}
|