public bool TakeCash(int num, bool notifyLowFunds = false) { if (Cash + Resources < num) { if (notifyLowFunds && Game.RunTime > lastNotificationTime + Info.InsufficientFundsNotificationInterval) { lastNotificationTime = Game.RunTime; Game.Sound.PlayNotification(owner.World.Map.Rules, owner, "Speech", Info.InsufficientFundsNotification, owner.Faction.InternalName); TextNotificationsManager.AddTransientLine(Info.InsufficientFundsTextNotification, owner); } return(false); } // Spend ore before cash Resources -= num; Spent += num; if (Resources < 0) { Cash += Resources; Resources = 0; } return(true); }
void INotifyInfiltrated.Infiltrated(Actor self, Actor infiltrator, BitSet <TargetableType> types) { if (!info.Types.Overlaps(types)) { return; } if (info.InfiltratedNotification != null) { Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", info.InfiltratedNotification, self.Owner.Faction.InternalName); } if (info.InfiltrationNotification != null) { Game.Sound.PlayNotification(self.World.Map.Rules, infiltrator.Owner, "Speech", info.InfiltrationNotification, infiltrator.Owner.Faction.InternalName); } TextNotificationsManager.AddTransientLine(info.InfiltratedTextNotification, self.Owner); TextNotificationsManager.AddTransientLine(info.InfiltrationTextNotification, infiltrator.Owner); infiltrator.Owner.Shroud.Explore(self.Owner.Shroud); var preventReset = self.Owner.PlayerActor.TraitsImplementing <IPreventsShroudReset>() .Any(p => p.PreventShroudReset(self)); if (!preventReset) { self.Owner.Shroud.ResetExploration(); } }
void INotifyInfiltrated.Infiltrated(Actor self, Actor infiltrator, BitSet <TargetableType> types) { if (!info.Types.Overlaps(types)) { return; } var targetResources = self.Owner.PlayerActor.Trait <PlayerResources>(); var spyResources = infiltrator.Owner.PlayerActor.Trait <PlayerResources>(); var spyValue = infiltrator.Info.TraitInfoOrDefault <ValuedInfo>(); var toTake = Math.Min(info.Maximum, (targetResources.Cash + targetResources.Resources) * info.Percentage / 100); var toGive = Math.Max(toTake, info.Minimum >= 0 ? info.Minimum : spyValue != null ? spyValue.Cost : 0); targetResources.TakeCash(toTake); spyResources.GiveCash(toGive); if (info.InfiltratedNotification != null) { Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", info.InfiltratedNotification, self.Owner.Faction.InternalName); } if (info.InfiltrationNotification != null) { Game.Sound.PlayNotification(self.World.Map.Rules, infiltrator.Owner, "Speech", info.InfiltrationNotification, infiltrator.Owner.Faction.InternalName); } TextNotificationsManager.AddTransientLine(info.InfiltratedTextNotification, self.Owner); TextNotificationsManager.AddTransientLine(info.InfiltrationTextNotification, infiltrator.Owner); if (info.ShowTicks) { self.World.AddFrameEndTask(w => w.Add(new FloatingText(self.CenterPosition, infiltrator.Owner.Color, FloatingText.FormatCashTick(toGive), 30))); } }
public void RepairBuilding(Actor self, Player player) { if (IsTraitDisabled || !self.AppearsFriendlyTo(player.PlayerActor)) { return; } // Remove the player if they are already repairing if (Repairers.Remove(player)) { UpdateCondition(self); return; } // Don't add new players if the limit has already been reached if (Repairers.Count >= Info.RepairBonuses.Length - 1) { return; } Repairers.Add(player); Game.Sound.PlayNotification(self.World.Map.Rules, player, "Speech", Info.RepairingNotification, player.Faction.InternalName); TextNotificationsManager.AddTransientLine(Info.RepairingTextNotification, self.Owner); UpdateCondition(self); }
public virtual void Target() { if (!Ready) { return; } var power = Instances.FirstOrDefault(i => !i.IsTraitPaused); if (power == null) { return; } if (!HasSufficientFunds(power)) { return; } Game.Sound.PlayToPlayer(SoundType.UI, Manager.Self.Owner, Info.SelectTargetSound); Game.Sound.PlayNotification(power.Self.World.Map.Rules, power.Self.Owner, "Speech", Info.SelectTargetSpeechNotification, power.Self.Owner.Faction.InternalName); TextNotificationsManager.AddTransientLine(Info.SelectTargetTextNotification, power.Self.Owner); power.SelectTarget(power.Self, Key, Manager); }
public override bool Tick(Actor self) { var sellValue = self.GetSellValue(); // Cast to long to avoid overflow when multiplying by the health var hp = health != null ? (long)health.HP : 1L; var maxHP = health != null ? (long)health.MaxHP : 1L; var refund = (int)((sellValue * sellableInfo.RefundPercent * hp) / (100 * maxHP)); refund = playerResources.ChangeCash(refund); foreach (var ns in self.TraitsImplementing <INotifySold>()) { ns.Sold(self); } if (showTicks && refund > 0 && self.Owner.IsAlliedWith(self.World.RenderPlayer)) { self.World.AddFrameEndTask(w => w.Add(new FloatingText(self.CenterPosition, self.Owner.Color, FloatingText.FormatCashTick(refund), 30))); } Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", sellableInfo.Notification, self.Owner.Faction.InternalName); TextNotificationsManager.AddTransientLine(sellableInfo.TextNotification, self.Owner); self.Dispose(); return(false); }
void INotifyInfiltrated.Infiltrated(Actor self, Actor infiltrator, BitSet <TargetableType> types) { if (!info.Types.Overlaps(types)) { return; } if (info.InfiltratedNotification != null) { Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", info.InfiltratedNotification, self.Owner.Faction.InternalName); } if (info.InfiltrationNotification != null) { Game.Sound.PlayNotification(self.World.Map.Rules, infiltrator.Owner, "Speech", info.InfiltrationNotification, infiltrator.Owner.Faction.InternalName); } TextNotificationsManager.AddTransientLine(info.InfiltratedTextNotification, self.Owner); TextNotificationsManager.AddTransientLine(info.InfiltrationTextNotification, infiltrator.Owner); infiltrator.World.AddFrameEndTask(w => w.CreateActor(info.Proxy, new TypeDictionary { new OwnerInit(infiltrator.Owner) })); }
void INotifyInfiltrated.Infiltrated(Actor self, Actor infiltrator, BitSet <TargetableType> types) { if (!info.Types.Overlaps(types)) { return; } if (info.InfiltratedNotification != null) { Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", info.InfiltratedNotification, self.Owner.Faction.InternalName); } if (info.InfiltrationNotification != null) { Game.Sound.PlayNotification(self.World.Map.Rules, infiltrator.Owner, "Speech", info.InfiltrationNotification, infiltrator.Owner.Faction.InternalName); } TextNotificationsManager.AddTransientLine(info.InfiltratedTextNotification, self.Owner); TextNotificationsManager.AddTransientLine(info.InfiltrationTextNotification, infiltrator.Owner); var manager = self.Owner.PlayerActor.Trait <SupportPowerManager>(); var powers = manager.GetPowersForActor(self).Where(sp => !sp.Disabled); foreach (var power in powers) { power.ResetTimer(); } }
void SetCondition(Actor self, bool granted) { if (granted && conditionToken == Actor.InvalidConditionToken) { conditionToken = self.GrantCondition(Info.Condition); if (Info.EnabledSound != null) { Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Sounds", Info.EnabledSound, self.Owner.Faction.InternalName); } if (Info.EnabledSpeech != null) { Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", Info.EnabledSpeech, self.Owner.Faction.InternalName); } TextNotificationsManager.AddTransientLine(Info.EnabledTextNotification, self.Owner); } else if (!granted && conditionToken != Actor.InvalidConditionToken) { conditionToken = self.RevokeCondition(conditionToken); if (Info.DisabledSound != null) { Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Sounds", Info.DisabledSound, self.Owner.Faction.InternalName); } if (Info.DisabledSpeech != null) { Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", Info.DisabledSpeech, self.Owner.Faction.InternalName); } TextNotificationsManager.AddTransientLine(Info.DisabledTextNotification, self.Owner); } }
public void OnDiscovered(Actor self, Player discoverer, bool playNotification) { if (!playNotification || discoverer != self.World.RenderPlayer) { return; } // Hack to disable notifications for neutral actors so some custom maps don't need fixing // At this point it's either neutral or an enemy if (!Info.AnnounceNeutrals && !self.AppearsHostileTo(discoverer.PlayerActor)) { return; } // Audio notification if (discoverer != null && !string.IsNullOrEmpty(Info.Notification)) { Game.Sound.PlayNotification(self.World.Map.Rules, discoverer, "Speech", Info.Notification, discoverer.Faction.InternalName); } if (discoverer != null) { TextNotificationsManager.AddTransientLine(Info.TextNotification, discoverer); } // Radar notification if (Info.PingRadar) { radarPings.Value?.Add(() => true, self.CenterPosition, Color.Red, 50); } }
public virtual void Charging(Actor self, string key) { Game.Sound.PlayToPlayer(SoundType.UI, self.Owner, Info.BeginChargeSound); Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", Info.BeginChargeSpeechNotification, self.Owner.Faction.InternalName); TextNotificationsManager.AddTransientLine(Info.BeginChargeTextNotification, self.Owner); }
void INotifyGameSaved.GameSaved(World world) { if (!world.IsReplay) { Game.Sound.PlayNotification(world.Map.Rules, null, "Speech", info.SavedNotification, world.RenderPlayer == null ? null : world.RenderPlayer.Faction.InternalName); TextNotificationsManager.AddTransientLine(info.SavedTextNotification, null); } }
void IWorldLoaded.WorldLoaded(World world, WorldRenderer wr) { if (!world.IsLoadingGameSave) { Game.Sound.PlayNotification(world.Map.Rules, null, "Speech", info.Notification, world.RenderPlayer == null ? null : world.RenderPlayer.Faction.InternalName); TextNotificationsManager.AddTransientLine(info.TextNotification, null); } }
void PlayNotification(Actor self) { Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", info.NewOptionsNotification, self.Owner.Faction.InternalName); TextNotificationsManager.AddTransientLine(info.NewOptionsTextNotification, self.Owner); triggerNotification = false; tick = 0; }
void RepairTick(Actor self) { var repairsUnits = allRepairsUnits.FirstOrDefault(r => !r.IsTraitDisabled && !r.IsTraitPaused); if (repairsUnits == null) { if (!allRepairsUnits.Any(r => r.IsTraitPaused)) { activeResupplyTypes &= ~ResupplyType.Repair; } return; } if (health.DamageState == DamageState.Undamaged) { if (host.Actor.Owner != self.Owner) { host.Actor.Owner.PlayerActor.TraitOrDefault <PlayerExperience>()?.GiveExperience(repairsUnits.Info.PlayerExperience); } Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", repairsUnits.Info.FinishRepairingNotification, self.Owner.Faction.InternalName); TextNotificationsManager.AddTransientLine(repairsUnits.Info.FinishRepairingTextNotification, self.Owner); activeResupplyTypes &= ~ResupplyType.Repair; return; } if (remainingTicks == 0) { var hpToRepair = repairable != null && repairable.Info.HpPerStep > 0 ? repairable.Info.HpPerStep : repairsUnits.Info.HpPerStep; // Cast to long to avoid overflow when multiplying by the health var value = (long)unitCost * repairsUnits.Info.ValuePercentage; var cost = value == 0 ? 0 : Math.Max(1, (int)(hpToRepair * value / (health.MaxHP * 100L))); if (!played) { played = true; Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", repairsUnits.Info.StartRepairingNotification, self.Owner.Faction.InternalName); TextNotificationsManager.AddTransientLine(repairsUnits.Info.StartRepairingTextNotification, self.Owner); } if (!playerResources.TakeCash(cost, true)) { remainingTicks = 1; return; } self.InflictDamage(host.Actor, new Damage(-hpToRepair, repairsUnits.Info.RepairDamageTypes)); remainingTicks = repairsUnits.Info.Interval; } else { --remainingTicks; } }
public override void SelectTarget(Actor self, string order, SupportPowerManager manager) { Game.Sound.PlayToPlayer(SoundType.UI, manager.Self.Owner, Info.SelectTargetSound); Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", Info.SelectTargetSpeechNotification, self.Owner.Faction.InternalName); TextNotificationsManager.AddTransientLine(Info.SelectTargetTextNotification, manager.Self.Owner); self.World.OrderGenerator = new SelectSpawnActorPowerTarget(order, manager, this, MouseButton.Left); }
void INotifyDamage.Damaged(Actor self, AttackInfo e) { var localPlayer = self.World.LocalPlayer; if (localPlayer == null || localPlayer.Spectating) { return; } if (e.Attacker == null) { return; } if (e.Attacker.Owner == self.Owner) { return; } if (e.Attacker == self.World.WorldActor) { return; } // Only track last hit against our base if (!self.Info.HasTraitInfo <BuildingInfo>()) { return; } if (e.Attacker.Owner.IsAlliedWith(self.Owner) && e.Damage.Value <= 0) { return; } if (Game.RunTime > lastAttackTime + info.NotifyInterval) { var rules = self.World.Map.Rules; if (self.Owner == localPlayer) { Game.Sound.PlayNotification(rules, self.Owner, "Speech", info.Notification, self.Owner.Faction.InternalName); TextNotificationsManager.AddTransientLine(info.TextNotification, self.Owner); } else if (localPlayer.IsAlliedWith(self.Owner) && localPlayer != e.Attacker.Owner) { Game.Sound.PlayNotification(rules, localPlayer, "Speech", info.AllyNotification, localPlayer.Faction.InternalName); TextNotificationsManager.AddTransientLine(info.AllyTextNotification, localPlayer); } radarPings?.Add(() => self.Owner.IsAlliedWith(self.World.RenderPlayer), self.CenterPosition, info.RadarPingColor, info.RadarPingDuration); lastAttackTime = Game.RunTime; } }
void INotifyCapture.OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner, BitSet <CaptureType> captureTypes) { var faction = info.NewOwnerVoice ? newOwner.Faction.InternalName : oldOwner.Faction.InternalName; Game.Sound.PlayNotification(self.World.Map.Rules, newOwner, "Speech", info.Notification, faction); TextNotificationsManager.AddTransientLine(info.TextNotification, newOwner); var loseFaction = info.LoseNewOwnerVoice ? newOwner.Faction.InternalName : oldOwner.Faction.InternalName; Game.Sound.PlayNotification(self.World.Map.Rules, oldOwner, "Speech", info.LoseNotification, loseFaction); TextNotificationsManager.AddTransientLine(info.LoseTextNotification, oldOwner); }
public virtual void Activate(Actor collector) { Game.Sound.Play(SoundType.World, Info.Sound, self.CenterPosition); if (!string.IsNullOrEmpty(Info.Notification)) Game.Sound.PlayNotification(self.World.Map.Rules, collector.Owner, "Speech", Info.Notification, collector.Owner.Faction.InternalName); TextNotificationsManager.AddTransientLine(Info.TextNotification, collector.Owner); if (Info.Image != null && Info.Sequence != null) collector.World.AddFrameEndTask(w => w.Add(new SpriteEffect(collector, w, Info.Image, Info.Sequence, Info.Palette))); }
protected override void Created(Actor self) { base.Created(self); var player = self.World.LocalPlayer; if (player != null && player != self.Owner) { Game.Sound.Play(SoundType.UI, Info.DetectedSound); Game.Sound.PlayNotification(self.World.Map.Rules, player, "Speech", info.DetectedSpeechNotification, player.Faction.InternalName); TextNotificationsManager.AddTransientLine(info.DetectedTextNotification, player); } }
public virtual void Charged(Actor self, string key) { Game.Sound.PlayToPlayer(SoundType.UI, self.Owner, Info.EndChargeSound); Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", Info.EndChargeSpeechNotification, self.Owner.Faction.InternalName); TextNotificationsManager.AddTransientLine(Info.EndChargeTextNotification, self.Owner); foreach (var notify in self.TraitsImplementing <INotifySupportPower>()) { notify.Charged(self); } }
protected void ClickIcon(SupportPowerIcon clicked) { if (!clicked.Power.Active) { Game.Sound.PlayToPlayer(SoundType.UI, spm.Self.Owner, clicked.Power.Info.InsufficientPowerSound); Game.Sound.PlayNotification(spm.Self.World.Map.Rules, spm.Self.Owner, "Speech", clicked.Power.Info.InsufficientPowerSpeechNotification, spm.Self.Owner.Faction.InternalName); TextNotificationsManager.AddTransientLine(clicked.Power.Info.InsufficientPowerTextNotification, spm.Self.Owner); } else { clicked.Power.Target(); } }
void ITick.Tick(Actor self) { if (Game.RunTime > lastSiloAdviceTime + info.AdviceInterval) { var owner = self.Owner; if (resources.Resources > info.Threshold * resources.ResourceCapacity / 100) { Game.Sound.PlayNotification(self.World.Map.Rules, owner, "Speech", info.Notification, owner.Faction.InternalName); TextNotificationsManager.AddTransientLine(info.TextNotification, owner); } lastSiloAdviceTime = Game.RunTime; } }
public override void Activate(Actor self, Order order, SupportPowerManager manager) { base.Activate(self, order, manager); PlayLaunchSounds(); var info = Info as ProduceActorPowerInfo; var producers = self.World.ActorsWithTrait <Production>() .Where(x => x.Actor.Owner == self.Owner && !x.Trait.IsTraitDisabled && x.Trait.Info.Produces.Contains(info.Type)) .OrderByDescending(x => x.Actor.IsPrimaryBuilding()) .ThenByDescending(x => x.Actor.ActorID); // TODO: The power should not reset if the production fails. // Fixing this will require a larger rework of the support power code var activated = false; foreach (var p in producers) { foreach (var name in info.Actors) { var ai = self.World.Map.Rules.Actors[name]; var inits = new TypeDictionary { new OwnerInit(self.Owner), new FactionInit(BuildableInfo.GetInitialFaction(ai, faction)) }; activated |= p.Trait.Produce(p.Actor, ai, info.Type, inits, 0); } if (activated) { break; } } if (activated) { Game.Sound.PlayNotification(self.World.Map.Rules, manager.Self.Owner, "Speech", info.ReadyAudio, self.Owner.Faction.InternalName); TextNotificationsManager.AddTransientLine(info.ReadyTextNotification, manager.Self.Owner); } else { Game.Sound.PlayNotification(self.World.Map.Rules, manager.Self.Owner, "Speech", info.BlockedAudio, self.Owner.Faction.InternalName); TextNotificationsManager.AddTransientLine(info.BlockedTextNotification, manager.Self.Owner); } }
void INotifyWinStateChanged.OnPlayerWon(Player player) { if (info.SuppressNotifications) { return; } TextNotificationsManager.AddSystemLine(player.PlayerName + " is victorious."); Game.RunAfterDelay(info.NotificationDelay, () => { if (Game.IsCurrentWorld(player.World) && player == player.World.LocalPlayer) { Game.Sound.PlayNotification(player.World.Map.Rules, player, "Speech", mo.Info.WinNotification, player.Faction.InternalName); TextNotificationsManager.AddTransientLine(mo.Info.WinTextNotification, player); } }); }
void OnQuit() { // TODO: Create a mechanism to do things like this cleaner. Also needed for scripted missions if (world.Type == WorldType.Regular) { var moi = world.Map.Rules.Actors[SystemActors.Player].TraitInfoOrDefault <MissionObjectivesInfo>(); if (moi != null) { var faction = world.LocalPlayer?.Faction.InternalName; Game.Sound.PlayNotification(world.Map.Rules, null, "Speech", moi.LeaveNotification, faction); TextNotificationsManager.AddTransientLine(moi.LeaveTextNotification, null); } } leaving = true; var iop = world.WorldActor.TraitsImplementing <IObjectivesPanel>().FirstOrDefault(); var exitDelay = iop?.ExitDelay ?? 0; if (mpe != null) { Game.RunAfterDelay(exitDelay, () => { if (Game.IsCurrentWorld(world)) { mpe.Fade(MenuPaletteEffect.EffectType.Black); } }); exitDelay += 40 * mpe.Info.FadeLength; } Game.RunAfterDelay(exitDelay, () => { if (!Game.IsCurrentWorld(world)) { return; } Game.Disconnect(); Ui.ResetAll(); Game.LoadShellMap(); }); }
void INotifyKilled.Killed(Actor self, AttackInfo e) { if (IsTraitDisabled) { return; } var localPlayer = self.World.LocalPlayer; if (localPlayer == null || localPlayer.Spectating) { return; } var player = Info.NotifyAll ? localPlayer : self.Owner; Game.Sound.PlayNotification(self.World.Map.Rules, player, "Speech", Info.Notification, self.Owner.Faction.InternalName); TextNotificationsManager.AddTransientLine(Info.TextNotification, player); }
public virtual void PlayLaunchSounds() { var localPlayer = Self.World.LocalPlayer; if (localPlayer == null || localPlayer.Spectating) { return; } var isAllied = Self.Owner.IsAlliedWith(localPlayer); Game.Sound.Play(SoundType.UI, isAllied ? Info.LaunchSound : Info.IncomingSound); var toPlayer = isAllied ? localPlayer ?? Self.Owner : localPlayer; var speech = isAllied ? Info.LaunchSpeechNotification : Info.IncomingSpeechNotification; Game.Sound.PlayNotification(Self.World.Map.Rules, toPlayer, "Speech", speech, toPlayer.Faction.InternalName); TextNotificationsManager.AddTransientLine(isAllied ? Info.LaunchTextNotification : Info.IncomingTextNotification, toPlayer); }
void INotifyWinStateChanged.OnPlayerLost(Player player) { foreach (var a in player.World.ActorsWithTrait <INotifyOwnerLost>().Where(a => a.Actor.Owner == player)) { a.Trait.OnOwnerLost(a.Actor); } if (info.SuppressNotifications) { return; } TextNotificationsManager.AddSystemLine(player.PlayerName + " is defeated."); Game.RunAfterDelay(info.NotificationDelay, () => { if (Game.IsCurrentWorld(player.World) && player == player.World.LocalPlayer) { Game.Sound.PlayNotification(player.World.Map.Rules, player, "Speech", mo.Info.LoseNotification, player.Faction.InternalName); TextNotificationsManager.AddTransientLine(mo.Info.LoseTextNotification, player); } }); }
void INotifyInfiltrated.Infiltrated(Actor self, Actor infiltrator, BitSet <TargetableType> types) { if (!info.Types.Overlaps(types)) { return; } if (info.InfiltratedNotification != null) { Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", info.InfiltratedNotification, self.Owner.Faction.InternalName); } if (info.InfiltrationNotification != null) { Game.Sound.PlayNotification(self.World.Map.Rules, infiltrator.Owner, "Speech", info.InfiltrationNotification, infiltrator.Owner.Faction.InternalName); } TextNotificationsManager.AddTransientLine(info.InfiltratedTextNotification, self.Owner); TextNotificationsManager.AddTransientLine(info.InfiltrationTextNotification, infiltrator.Owner); playerPower.TriggerPowerOutage(info.Duration); }