diff --git a/OpenRA.Mods.Common/Scripting/Global/TriggerGlobal.cs b/OpenRA.Mods.Common/Scripting/Global/TriggerGlobal.cs index e64fe77646..5085a319d5 100644 --- a/OpenRA.Mods.Common/Scripting/Global/TriggerGlobal.cs +++ b/OpenRA.Mods.Common/Scripting/Global/TriggerGlobal.cs @@ -406,6 +406,20 @@ namespace OpenRA.Mods.Common.Scripting GetScriptTriggers(a).RegisterCallback(Trigger.OnInfiltrated, func, Context); } + [Desc("Call a function when this actor is discovered by an enemy or a player with a Neutral stance. " + + "The callback function will be called as func(Actor discovered, Player discoverer)")] + public void OnDiscovered(Actor a, LuaFunction func) + { + GetScriptTriggers(a).RegisterCallback(Trigger.OnDiscovered, func, Context); + } + + [Desc("Call a function when this player is discovered by an enemy or neutral player. " + + "The callback function will be called as func(Player discovered, Player discoverer, Actor discoveredActor)")] + public void OnPlayerDiscovered(Player discovered, LuaFunction func) + { + GetScriptTriggers(discovered.PlayerActor).RegisterCallback(Trigger.OnPlayerDiscovered, func, Context); + } + [Desc("Removes all triggers from this actor." + "Note that the removal will only take effect at the end of a tick, " + "so you must not add new triggers at the same time that you are calling this function.")] diff --git a/OpenRA.Mods.Common/Scripting/ScriptTriggers.cs b/OpenRA.Mods.Common/Scripting/ScriptTriggers.cs index 3c887b6028..298cb806fb 100644 --- a/OpenRA.Mods.Common/Scripting/ScriptTriggers.cs +++ b/OpenRA.Mods.Common/Scripting/ScriptTriggers.cs @@ -21,7 +21,8 @@ namespace OpenRA.Mods.Common.Scripting public enum Trigger { OnIdle, OnDamaged, OnKilled, OnProduction, OnOtherProduction, OnPlayerWon, OnPlayerLost, - OnObjectiveAdded, OnObjectiveCompleted, OnObjectiveFailed, OnCapture, OnInfiltrated, OnAddedToWorld, OnRemovedFromWorld + OnObjectiveAdded, OnObjectiveCompleted, OnObjectiveFailed, OnCapture, OnInfiltrated, + OnAddedToWorld, OnRemovedFromWorld, OnDiscovered, OnPlayerDiscovered } [Desc("Allows map scripts to attach triggers to this actor via the Triggers global.")] @@ -31,7 +32,7 @@ namespace OpenRA.Mods.Common.Scripting } public sealed class ScriptTriggers : INotifyIdle, INotifyDamage, INotifyKilled, INotifyProduction, INotifyOtherProduction, - INotifyObjectivesUpdated, INotifyCapture, INotifyInfiltrated, INotifyAddedToWorld, INotifyRemovedFromWorld, IDisposable + INotifyObjectivesUpdated, INotifyCapture, INotifyInfiltrated, INotifyAddedToWorld, INotifyRemovedFromWorld, IDisposable, INotifyDiscovered { readonly World world; @@ -324,6 +325,40 @@ namespace OpenRA.Mods.Common.Scripting OnOtherProducedInternal(producee, produced); } + public void OnDiscovered(Actor self, Player discoverer, bool playNotification) + { + foreach (var f in Triggers[Trigger.OnDiscovered]) + { + try + { + using (var a = self.ToLuaValue(f.Second)) + using (var b = discoverer.ToLuaValue(f.Second)) + f.First.Call(a, b).Dispose(); + } + catch (Exception ex) + { + f.Second.FatalError(ex.Message); + return; + } + } + + foreach (var f in Triggers[Trigger.OnPlayerDiscovered]) + { + try + { + using (var a = self.Owner.ToLuaValue(f.Second)) + using (var b = discoverer.ToLuaValue(f.Second)) + using (var c = self.ToLuaValue(f.Second)) + f.First.Call(a, b, c).Dispose(); + } + catch (Exception ex) + { + f.Second.FatalError(ex.Message); + return; + } + } + } + public void Clear(Trigger trigger) { world.AddFrameEndTask(w => diff --git a/mods/cnc/maps/gdi05a/gdi05a.lua b/mods/cnc/maps/gdi05a/gdi05a.lua index bb26935e74..beb5b8db88 100644 --- a/mods/cnc/maps/gdi05a/gdi05a.lua +++ b/mods/cnc/maps/gdi05a/gdi05a.lua @@ -11,11 +11,6 @@ GdiTanks = { "mtnk", "mtnk" } GdiApc = { "apc" } GdiInfantry = { "e1", "e1", "e1", "e1", "e1", "e2", "e2", "e2", "e2", "e2" } GdiBase = { GdiNuke1, GdiNuke2, GdiProc, GdiSilo1, GdiSilo2, GdiPyle, GdiWeap, GdiHarv } -GdiBaseDiscoveryTrigger = -{ - CPos.New(39, 54), CPos.New(48, 42), CPos.New(49, 42), CPos.New(50, 42), CPos.New(51, 42), - CPos.New(52, 42), CPos.New(53, 42), CPos.New(54, 42), CPos.New(55, 42), CPos.New(56, 42) -} NodSams = { Sam1, Sam2, Sam3, Sam4 } CoreNodBase = { NodConYard, NodRefinery, HandOfNod, Airfield } @@ -122,7 +117,11 @@ Grd3Action = function() end end -DiscoverGdiBase = function() +DiscoverGdiBase = function(actor, discoverer) + if baseDiscovered or not discoverer == gdi then + return + end + Utils.Do(GdiBase, function(actor) actor.Owner = gdi end) @@ -145,12 +144,7 @@ SetupWorld = function() Reinforcements.Reinforce(gdi, GdiApc, { GdiApcEntry.Location, GdiApcRallyPoint.Location }, DateTime.Seconds(1), function(actor) actor.Stance = "Defend" end) Reinforcements.Reinforce(gdi, GdiInfantry, { GdiInfantryEntry.Location, GdiInfantryRallyPoint.Location }, 15, function(actor) actor.Stance = "Defend" end) - Trigger.OnEnteredFootprint(GdiBaseDiscoveryTrigger, function(actor, id) - if actor.Owner == gdi then - DiscoverGdiBase() - Trigger.RemoveFootprintTrigger(id) - end - end) + Trigger.OnPlayerDiscovered(gdiBase, DiscoverGdiBase) Utils.Do(Map.NamedActors, function(actor) if actor.Owner == nod and actor.HasProperty("StartBuildingRepairs") then @@ -186,6 +180,7 @@ SetupWorld = function() end WorldLoaded = function() + gdiBase = Player.GetPlayer("AbandonedBase") gdi = Player.GetPlayer("GDI") nod = Player.GetPlayer("Nod") diff --git a/mods/cnc/maps/gdi05a/map.yaml b/mods/cnc/maps/gdi05a/map.yaml index 47703b3908..4b62f85ebf 100644 --- a/mods/cnc/maps/gdi05a/map.yaml +++ b/mods/cnc/maps/gdi05a/map.yaml @@ -2,7 +2,7 @@ MapFormat: 7 RequiresMod: cnc -Title: Repair the GDI base +Title: Repair the GDI base (a) Description: A GDI field base is under attack. They have fended off one attack but will not survive another.\n\nMove to the base, repair the structures and then launch a strike force to destroy the Nod base in the area.\n\nDestroy all Nod units and structures. @@ -56,6 +56,11 @@ Players: LockTeam: True Allies: GDI Enemies: Nod + PlayerReference@AbandonedBase: + Name: AbandonedBase + NonCombatant: True + ColorRamp: 31,222,183 + Race: gdi PlayerReference@Neutral: Name: Neutral OwnsWorld: True @@ -684,36 +689,36 @@ Actors: Owner: Neutral GdiProc: proc Location: 50,51 - Owner: Neutral + Owner: AbandonedBase Health: 0.3085938 FreeActor: False GdiHarv: harv Location: 48,53 - Owner: Neutral + Owner: AbandonedBase Facing: 64 GdiWeap: weap Location: 50,54 - Owner: Neutral + Owner: AbandonedBase Health: 0.2695313 GdiNuke1: nuke Location: 53,55 - Owner: Neutral + Owner: AbandonedBase Health: 0.2890625 GdiPyle: pyle Location: 46,55 - Owner: Neutral + Owner: AbandonedBase Health: 0.25 GdiSilo1: silo Location: 53,51 - Owner: Neutral + Owner: AbandonedBase Health: 0.3320313 GdiSilo2: silo Location: 53,53 - Owner: Neutral + Owner: AbandonedBase Health: 0.25 GdiNuke2: nuke Location: 48,56 - Owner: Neutral + Owner: AbandonedBase Health: 0.2070313 NodConYard: fact Location: 9,29 @@ -796,6 +801,7 @@ Rules: -ConquestVictoryConditions: MissionObjectives: EarlyGameOver: true + EnemyWatcher: ^Vehicle: Tooltip: GenericVisibility: Enemy @@ -826,6 +832,7 @@ Rules: Tooltip: GenericVisibility: Enemy ShowOwnerRow: false + AnnounceOnSeen: ^Wall: Tooltip: ShowOwnerRow: false