//the Move method is called when another component requests the movement of a list of units public void Move(List <Unit> units, Vector3 destination, float offsetRadius, Entity target, InputMode targetMode, bool playerCommand) { if (units.Count == 1) //if there's only one unit in the list { Move(units[0], destination, offsetRadius, target, targetMode, playerCommand); //use the one-unit movement return; } if (GameManager.MultiplayerGame == false) //single player game, directly prepare the unit's list movement { PrepareMove(units, destination, offsetRadius, target, targetMode, playerCommand); } else if (RTSHelper.IsLocalPlayer(units[0]) == true) //multiplayer game and this is the local player { //send input action to the input manager NetworkInput newInput = new NetworkInput() { sourceMode = (byte)InputMode.unitGroup, targetMode = (byte)targetMode, targetPosition = destination, value = Mathf.FloorToInt(offsetRadius), groupSourceID = InputManager.UnitListToString(units) }; //sent input InputManager.SendInput(newInput, null, target); } }
//enable an attack entity public ErrorMessage EnableAttack(int ID) { //if the attack type is locked then it can't be activated if (AttackEntities[ID].IsLocked) { return(ErrorMessage.attackTypeLocked); } else if (AttackEntities[ID].CoolDownActive == true) //if the target attack type is in cool down right now: { return(ErrorMessage.attackInCooldown); } if (GameManager.MultiplayerGame == false) //single player game -> directly enable attack entity { EnableAttackLocal(ID); } else if (RTSHelper.IsLocalPlayer(activeAttack.FactionEntity)) { NetworkInput newInput = new NetworkInput() { sourceMode = (byte)InputMode.factionEntity, targetMode = (byte)InputMode.multipleAttack, value = ID }; InputManager.SendInput(newInput, factionEntity, null); //send input to input manager } return(ErrorMessage.none); }
//a method that launches the attack movement of a list of units public void LaunchAttack(List <Unit> units, FactionEntity targetEntity, Vector3 targetPosition, AttackModes attackMode, bool playerCommand) { if (units.Count == 1) //one unit only? { //use the one-unit attack movement LaunchAttack(units[0], targetEntity, targetPosition, attackMode, playerCommand); return; } if (GameManager.MultiplayerGame == false) //single player game, directly prepare the unit's attack movement { PrepareMove(units, targetPosition, targetEntity ? targetEntity.GetRadius() : 0.0f, targetEntity, InputMode.attack, playerCommand, true, attackMode, targetEntity); } else if (RTSHelper.IsLocalPlayer(units[0]) == true) //multiplayer game and this is the local player { //send input action to the input manager NetworkInput newInput = new NetworkInput() { sourceMode = (byte)InputMode.unitGroup, targetMode = (byte)InputMode.attack, targetPosition = targetPosition, value = (int)attackMode, groupSourceID = InputManager.UnitListToString(units) }; //sent input InputManager.SendInput(newInput, null, targetEntity); } }
//a method called when the unit's health has been updated: public override void OnHealthUpdated(int value, FactionEntity source) { base.OnHealthUpdated(value, source); CustomEvents.OnUnitHealthUpdated(unit, value, source); if (value < 0) //if the unit's health has been decreased { unit.SetAnimState(UnitAnimState.takingDamage); //set the animator state to taking damage. if (stopMovingOnDamage == true) //stop player movement on damage if this is set to true { unit.MovementComp.Stop(); } if (enableDamageAnimation == true) //if the damage animation is enabled { damageAnimationTimer = damageAnimationDuration; //start the timer. damageAnimationActive = true; //mark as active } if (source != null && (GameManager.MultiplayerGame == false || RTSHelper.IsLocalPlayer(unit) == true)) //if the attack source is known and this is either a single player game or the local player's unit { //if the unit has an attack component and it can attack back and it is idle if (unit.AttackComp != null && unit.AttackComp.IsActive() && unit.AttackComp.CanEngageWhenAttacked() == true && unit.IsIdle() == true) { gameMgr.MvtMgr.LaunchAttack(unit, source, source.GetSelection().transform.position, MovementManager.AttackModes.none, false); //launch attack at the source } TriggerEscapeOnAttack(); //attempt to trigger the escape on attack behavior if it is enabled } } }
//a method to trigger the escape on attack behavior public void Trigger() { if (isActive == false) //do not proceed if the component is not active { return; } Vector3 targetPosition = gameMgr.MvtMgr.GetRandomMovablePosition(transform.position, range.getRandomValue(), unit, unit.MovementComp.GetAgentAreaMask()); //find a random position to escape to if (GameManager.MultiplayerGame == false) //single player game { TriggerLocal(targetPosition); } else if (RTSHelper.IsLocalPlayer(unit) == true) //multiplayer game and this is the local player { NetworkInput newInput = new NetworkInput() //create new input for the escape task { sourceMode = (byte)InputMode.unit, targetMode = (byte)InputMode.unitEscape, initialPosition = transform.position, targetPosition = targetPosition }; InputManager.SendInput(newInput, unit, null); //send input to input manager } }
//a method to collect resources. public void CollectResources(int generatorID) { generators[generatorID].OnResourceCollected(building.FactionID); //collect the resources and reset the generator's settings if (RTSHelper.IsLocalPlayer(building)) //if this is the local player: { CustomEvents.OnResourceGeneratorCollected(this, generatorID); //trigger custom event AudioManager.Play(gameMgr.GetGeneralAudioSource(), collectionAudio, false); //plau the collection audio } }
public void Init(GameManager gameMgr, Building building) { this.gameMgr = gameMgr; this.building = building; foreach (Generator g in generators) //go through all the available generators { g.Init(gameMgr); //init the generator's settings } if (GameManager.MultiplayerGame == true && !RTSHelper.IsLocalPlayer(building)) //if it's a multiplayer game and this does not belong to the local player's faction. { enabled = false; //disable this component } IsActive = true; }
//a method called when the resource object is to be destroyed public void DestroyResource(Unit source) { if (GameManager.MultiplayerGame == false) //if this is a single player game -> go ahead directly { DestroyResourceLocal(source); } else if (RTSHelper.IsLocalPlayer(source)) //multiplayer game and the resource collector belongs to the local faction { NetworkInput newInput = new NetworkInput() { sourceMode = (byte)InputMode.destroy, targetMode = (byte)InputMode.resource, }; InputManager.SendInput(newInput, this, source); } }
//a method that is used to move the unit to its initial position after it spawns: public void SetInitialTargetPosition(Building source, Vector3 gotoPosition) { Creator = source; //set the building creator //only if the is owned by the local player or this is not a multiplayer game if (RTSHelper.IsLocalPlayer(this) || GameManager.MultiplayerGame == false) { if (Creator != null) //if the creator is assigned { Creator.SendUnitToRallyPoint(this); //send unit to rally point } else if (Vector3.Distance(gotoPosition, transform.position) > gameMgr.MvtMgr.GetStoppingDistance()) //only if the goto position is not within the stopping distance of this unit { gameMgr.MvtMgr.Move(this, gotoPosition, 0.0f, null, InputMode.movement, false); //no creator building? move player to its goto position } } }
//add/remove to/from the resource public void AddAmount(int value, Unit source) { if (GameManager.MultiplayerGame == false) //if this is a single player game -> go ahead directly { AddAmountLocal(value, source); } else if (RTSHelper.IsLocalPlayer(source)) //multiplayer game and the resource collector belongs to the local faction { NetworkInput newInput = new NetworkInput() { sourceMode = (byte)InputMode.resource, targetMode = (byte)InputMode.health, value = value }; InputManager.SendInput(newInput, this, source); } }
//update when the unit doesn't have a target protected virtual void OnInactiveUpdate() { if (inProgress == true) //if the unit doesn't have a target but its job is marked as in progress { Stop(); //cancel job } if ((GameManager.MultiplayerGame == false || RTSHelper.IsLocalPlayer(unit)) && autoBehavior.IsEnabled() == true && unit.IsIdle() == true) //if the auto behavior is, the unit is idle and this is the local player's faction or a single player game { if (autoBehavior.CanSearch() == true) //can the unit search for a target { OnTargetSearch(); } else { autoBehavior.UpdateTimer(); //update the timer. } } }
//a method that sends the unit to drop off resources at the drop off building public void SendToDropOff() { if (GameManager.MultiplayerGame == false) //if this is a singleplayer game then go ahead directly { SendToDropOffLocal(); } else if (RTSHelper.IsLocalPlayer(unit)) //multiplayer game and this is the collector's owner { NetworkInput newInput = new NetworkInput() { sourceMode = (byte)InputMode.unit, targetMode = (byte)InputMode.dropoff, initialPosition = transform.position }; InputManager.SendInput(newInput, unit, dropOffBuilding); } }
//a method called to eject all units public void EjectAll(bool destroyed) { if (GameManager.MultiplayerGame == false) //if this is a singleplayer game then go ahead directly { EjectAllLocal(destroyed); } else if (RTSHelper.IsLocalPlayer(FactionEntity)) //multiplayer game and this is the APC's owner { NetworkInput newInput = new NetworkInput() { sourceMode = (byte)InputMode.APC, targetMode = (byte)InputMode.APCEjectAll, value = destroyed == true ? 1 : 0 }; InputManager.SendInput(newInput, FactionEntity, null); //send input to input manager } }
//called when the building picks a target public override void SetTarget(FactionEntity newTarget, Vector3 newTargetPosition) { if (GameManager.MultiplayerGame == false) //single player game, go ahead { SetTargetLocal(newTarget, newTargetPosition); } else if (RTSHelper.IsLocalPlayer(building) == true) //only if this is a local player { NetworkInput newInput = new NetworkInput() { sourceMode = (byte)InputMode.building, targetMode = (byte)InputMode.attack, targetPosition = newTargetPosition, }; InputManager.SendInput(newInput, building, newTarget); //send input return; } }
public void Init(GameManager gameMgr, Unit unit) { this.gameMgr = gameMgr; this.unit = unit; if (isActive == false || activeByDefault == false) //if the Wandering component is either not enabled or unit can't wander when created { return; //do not proceed } if (GameManager.MultiplayerGame == false || RTSHelper.IsLocalPlayer(unit)) //if this is a single player game or the local player owns this object { //set the wandering center if (fixedCenter == true) { center = transform.position; } Trigger(); } }
//a method that checks if the building is near a specific resource that it's supposed to built in range of public bool IsBuildingNearResource() { //if we can place the building free from being in range of a resource or this is not the player's faction (as this doesn't apply for NPC factions, they are managed differently). if (placeNearResource == false || RTSHelper.IsLocalPlayer(building) == false) { return(true); } foreach (Resource resource in gameMgr.ResourceMgr.GetAllResources()) //go through all resources { if (resource.GetResourceType() == resourceType) //make sure this is the resource that the building needs (matching names) { if (Vector3.Distance(resource.transform.position, transform.position) < resourceRange) //if the building is inside the correct range { return(true); //found requested resource } } } return(false); //failure in case no resource that matched the requested settings is found }
//a method called to destroy the faction entity: public void DestroyFactionEntity(bool upgrade) { if (GameManager.MultiplayerGame == false) //if it's a single player game { DestroyFactionEntityLocal(upgrade); //destroy faction entity directly } else //multiplayer game { if (RTSHelper.IsLocalPlayer(factionEntity)) //make sure that it's this faction entity belongs to the local player { //send input action to the input manager NetworkInput NewInputAction = new NetworkInput { sourceMode = (byte)InputMode.destroy, targetMode = (byte)InputMode.factionEntity, value = (upgrade == true) ? 1 : 0 //when upgrade == true, then set to 1. if not set to 0 }; InputManager.SendInput(NewInputAction, factionEntity, null); //send to input manager } } }
//called when the unit attempts to set a new target public virtual ErrorMessage SetTarget(E newTarget, InputMode targetMode = InputMode.none) { if (GameManager.MultiplayerGame == false) //if this is a singleplayer game then go ahead directly { SetTargetLocal(newTarget); } else if (RTSHelper.IsLocalPlayer(unit)) //multiplayer game and this is the unit's owner { NetworkInput newInput = new NetworkInput() { sourceMode = (byte)InputMode.unit, targetMode = (byte)targetMode, initialPosition = transform.position, targetPosition = newTarget.transform.position }; InputManager.SendInput(newInput, unit, newTarget); } return(ErrorMessage.none); }
//add/remove health to the faction entity's: public void AddHealth(int value, FactionEntity source) { if (GameManager.MultiplayerGame == false) //if it's a single player game { AddHealthLocal(value, source); //add the health directly } else //multiplayer game { if (RTSHelper.IsLocalPlayer(factionEntity)) //make sure that it's this faction entity belongs to the local player { //crete new input NetworkInput newInput = new NetworkInput { sourceMode = (byte)InputMode.factionEntity, targetMode = (byte)InputMode.health, value = value }; //send the input to the input manager InputManager.SendInput(newInput, factionEntity, source); } } }
protected void Update() { if (isDead == true || (GameManager.MultiplayerGame == true && RTSHelper.IsLocalPlayer(unit) == false)) //if this is a multiplayer game and this is not the local player or the unit is dead { return; //do not proceed } if (enableDamageAnimation == true && damageAnimationActive == true) //if the damage animation is enabled and it is currently active { if (damageAnimationTimer > 0) //the damage animation timer { damageAnimationTimer -= Time.deltaTime; } if (damageAnimationTimer < 0) { damageAnimationActive = false; damageAnimationTimer = 0.0f; //reset the timer unit.SetAnimState(UnitAnimState.idle); //back to idle animation TriggerEscapeOnAttack(); //attempt to trigger the escape on attack behavior if it is enabled } } }
//the Move method is called when another component requests the movement of a single unit public void Move(Unit unit, Vector3 destination, float offsetRadius, Entity target, InputMode targetMode, bool playerCommand) { if (GameManager.MultiplayerGame == false) //single player game, directly prepare the unit's movement { PrepareMove(unit, destination, offsetRadius, target, targetMode, playerCommand); } else if (RTSHelper.IsLocalPlayer(unit)) //multiplayer game and this is the local player { //send input action to the input manager NetworkInput newInput = new NetworkInput() { sourceMode = (byte)InputMode.unit, targetMode = (byte)targetMode, initialPosition = unit.transform.position, targetPosition = destination, value = Mathf.FloorToInt(offsetRadius) }; //sent input InputManager.SendInput(newInput, unit, target); } }
//a method that launches an attack movement for a single unit public void LaunchAttack(Unit unit, FactionEntity targetEntity, Vector3 targetPosition, AttackModes attackMode, bool playerCommand) { if (GameManager.MultiplayerGame == false) //single player game, directly prepare the unit's attack movement { PrepareMove(unit, targetPosition, targetEntity ? targetEntity.GetRadius() : 0.0f, targetEntity, InputMode.attack, playerCommand, true, attackMode, targetEntity); } else if (RTSHelper.IsLocalPlayer(unit) == true) //multiplayer game and this is the local player { //send input action to the input manager NetworkInput newInput = new NetworkInput() { sourceMode = (byte)InputMode.unit, targetMode = (byte)InputMode.attack, initialPosition = unit.transform.position, targetPosition = targetPosition, value = (int)attackMode, }; //sent input InputManager.SendInput(newInput, unit, targetEntity); } }
//a method called to eject one unit public void Eject(Unit unit, bool destroyed) { if (unit == null || storedUnits.Contains(unit) == false) //invalid unit or unit that's not stored here? { return; } if (GameManager.MultiplayerGame == false) //if this is a singleplayer game then go ahead directly { EjectLocal(unit, destroyed); } else if (RTSHelper.IsLocalPlayer(FactionEntity)) //multiplayer game and this is the APC's owner { NetworkInput newInput = new NetworkInput() { sourceMode = (byte)InputMode.APC, targetMode = (byte)InputMode.APCEject, value = destroyed == true ? 1 : 0 }; InputManager.SendInput(newInput, FactionEntity, unit); //send input to input manager } }
//update the attack entity when there's no target protected virtual void OnNoTargetUpdate() { weapon.UpdateIdleRotation(); if (gameMgr.InPeaceTime() == true) //game is still in peace time { return; } //if the attacker belongs to the local faction, the attacker can attack in range and it is in idle mode if (engageInRange == true && (GameManager.MultiplayerGame == false || RTSHelper.IsLocalPlayer(FactionEntity)) && IsIdle() == true) { if (searchTimer > 0) { searchTimer -= Time.deltaTime; } else { SearchTarget(); searchTimer = searchReload; //reload search timer } } }
//a method that converts this unit to the converter's faction public void Convert(Unit converter, int targetFactionID) { if (targetFactionID == FactionID) //if the converter and this unit have the same faction, then, what a waste of time and resources. { return; } if (GameManager.MultiplayerGame == false) //if this is a single player game { ConvertLocal(converter, targetFactionID); //convert unit directly } else if (RTSHelper.IsLocalPlayer(this)) //online game and this is the local player { NetworkInput newInput = new NetworkInput() { sourceMode = (byte)InputMode.unit, targetMode = (byte)InputMode.convert, initialPosition = transform.position, value = targetFactionID }; InputManager.SendInput(newInput, this, converter); //send conversion input to the input manager } }
private void Update() { if (isActive == false || unit.HealthComp.IsDead() == true || (GameManager.MultiplayerGame == true && !RTSHelper.IsLocalPlayer(unit))) //if this is not enabled or this is a multiplayer game where this is not the local player's unit { return; //do not proceed } if (unit.IsIdle() == true && unit.HealthComp.IsDamageAnimationActive() == false) //only if the player is idle and can wander + is not currently playing the take damage animation { //as long as the wander timer is running, do nothing if (timer > 0) { timer -= Time.deltaTime; } if (timer <= 0) //when the wander timer is over { Trigger(); //trigger it again } } }