/// <summary> /// Begin path finding to a new location. /// </summary> /// <param name="newLocation">The location to move to.</param> internal void MoveToNewLocation(LocationSubject newLocation) { if (newLocation == null) { Debug.Log("AnimalObjectScript::MoveToNewLocation() \n Error: null location"); return; } if (destination != null) { if (destination.SubjectID == newLocation.SubjectID) { return; } } // remove chase target if we're moving to a location chaseTarget = null; destination = newLocation; isCurrentLocationExplored = false; // queue up the waypoints for the new location // flip a coin on which method of area waypoints to use if (UnityEngine.Random.Range(0.0f, 1.0f) > 0.5f) { destinationWayPoints = newLocation.GetAreaWaypoints(npcCharacter.SightRangeNear); if (destinationWayPoints.Length > 1) { destinationWayPoints = ShiftToNearestFirst(destinationWayPoints); } } else { destinationWayPoints = newLocation.GetAreaWaypoints(npcCharacter.SightRangeNear, 1); if (destinationWayPoints.Length > 1) { destinationWayPoints = destinationWayPoints .OrderBy(o => Vector3.Distance(transform.position, o)) .ToArray(); } } // debugging- show generated waypoints in editor interface for (int i = 0; i < destinationWayPoints.Length; i++) { Color waypointColor = Color.red; if (subject.SubjectID == DbIds.Plinkett) { waypointColor = Color.blue; } if (subject.SubjectID == DbIds.Gobber) { waypointColor = Color.yellow; } Vector3 wayPtTop = new Vector3(destinationWayPoints[i].x, 0.25f + ((float)i / destinationWayPoints.Length) * 0.5f, destinationWayPoints[i].z); Debug.DrawLine(destinationWayPoints[i], wayPtTop, waypointColor, 10.0f); } currentWaypointIndex = 0; }
/// <summary> /// Chase the target until ChaseStop() is called. /// </summary> /// <param name="target">The object scripte of the game object to chase.</param> internal void ChaseStart(SubjectObjectScript target) { // remove destination while chasing a target destination = null; if (chaseTarget != null) { if (chaseTarget.GetInstanceID() != target.GetInstanceID()) { chaseTarget = target; } } else { chaseTarget = target; } }
public void TestSet6() { // make the selected target hungry. if (lastSelector != null) { SubjectObjectScript objScript = lastSelector.GetComponentInParent <SubjectObjectScript>(); if (objScript != null) { if (objScript.GetType() == typeof(AnimalObjectScript)) { AnimalObjectScript animal = objScript as AnimalObjectScript; animal.T_Npc.T_SetValues(newFood: animal.T_Npc.Definition.FoodHungry); } } } }
/// <summary> /// Instantiates newSubjectId's prefab at the spawnPoint position. /// </summary> /// <param name="newSubjectId">The SubjectID of the NPC to spawn.</param> /// <param name="spawnPoint">The position to spawn the NPC at.</param> public GameObject SpawnObject(int newSubjectId, Vector3 spawnPoint) { //Use the id to pull the Subject card Subject newSubject = masterSubjectList.GetSubject(newSubjectId); if (newSubject != null) { GameObject newObject = Instantiate(newSubject.Prefab, spawnPoint, Quaternion.identity); if (newObject != null) { SubjectObjectScript script = newObject.GetComponent <SubjectObjectScript>() as SubjectObjectScript; script.InitializeFromSubject(masterSubjectList, newSubject); return(newObject); } } return(null); }
/// <summary> /// Add objectToInspect to the NPC's Memories. /// </summary> /// <param name="objectToInspect">The GameObject to learn about.</param> internal void Inspect(GameObject objectToInspect) { // inspect the object, add to memories. SubjectObjectScript inspectObjectScript = objectToInspect.GetComponent <SubjectObjectScript>(); if (inspectObjectScript.GetType() == typeof(LocationObjectScript)) { LocationObjectScript locObjScript = inspectObjectScript as LocationObjectScript; //only add location to memory if all waypoints are explored if (objectScript.IsCurrentLocationExplored) { // if it's in the unexploredLocations list, remove it. unexploredLocations.Remove(locObjScript.Subject as LocationSubject); // if it's in the reExploreLocations list, remove it. reExploreLocations.Remove(locObjScript.Subject as LocationSubject); } } else { inspectObjectScript.Subject.TeachNpc(this); } }
/// <summary> /// UpdateRelatedInLocation finds objects inside the location and adds them to the relatedSubjects locally /// </summary> public void UpdateRelatedInLocation() { LocationSubject locationSubject = subject as LocationSubject; if (locationSubject == null) { return; } //grab collides within the area of our location and create a list of objects int layerMask = ~((1 << 8) | (1 << 9)); // filter out terrain and locations Collider[] hitColliders = Physics.OverlapSphere(locationSubject.Coordinates, locationSubject.Radius, layerMask); List <int> foundSubjectIDs = new List <int>(); localObjects.Clear(); for (int i = 0; i < hitColliders.Length; i++) { // get the base script class for our objects SubjectObjectScript script = hitColliders[i].GetComponent <SubjectObjectScript>() as SubjectObjectScript; if (script == null) { Debug.Log("SubjectObjectScript was not assigned to " + hitColliders[i].name); continue; } //tell each Object that it is within our location script.Location = subject as LocationSubject; //record each subjectID found if not already recorded int foundID = script.Subject.SubjectID; if (!foundSubjectIDs.Contains(foundID)) { foundSubjectIDs.Add(foundID); } //record object quantites for NPC memory ObjectMemory existingMemory = localObjects.Find(o => o.SubjectID == script.Subject.SubjectID); if (existingMemory != null) { existingMemory.Quantity++; } else { localObjects.Add(new ObjectMemory() { Quantity = 1, SubjectID = script.Subject.SubjectID }); } } //Compare to old so that we may not need to publish to master int[] newRelated = new int[foundSubjectIDs.Count]; newRelated = foundSubjectIDs.ToArray(); if (newRelated.Length != subject.RelatedSubjects.Length) { isChanged = true; } else { for (int i = 0; i < newRelated.Length; i++) { if (newRelated[i] != subject.RelatedSubjects[i]) { isChanged = true; break; } } } //Store output in local subject copy subject.RelatedSubjects = foundSubjectIDs.ToArray(); }
// Update is called once per frame void Update() { if (!npcCharacter.IsDead) { MetabolizeTickCounter += Time.deltaTime; if (MetabolizeTickCounter >= npcCharacter.Definition.MetabolizeInterval) { int healthChange = npcCharacter.Metabolize(); MetabolizeTickCounter -= npcCharacter.Definition.MetabolizeInterval; if (healthChange > 0) { GameObject.FindGameObjectWithTag("GameController").GetComponent <PlacementControllerScript>().PopMessage(healthChange.ToString(), gameObject.transform.position, 2); } else if (healthChange < 0) { GameObject.FindGameObjectWithTag("GameController").GetComponent <PlacementControllerScript>().PopMessage(healthChange.ToString(), gameObject.transform.position, 0); } } AiCoreTickCounter += Time.deltaTime; if (AiCoreTickCounter > AiTickRate) { npcCharacter.AiCoreProcess(); AiCoreTickCounter -= AiTickRate; } // === Movement === if (destination != null) // traveling to a new location { if (destinationWayPoints.Length != 0) { float distance = Vector3.Distance(destinationWayPoints[currentWaypointIndex], transform.position); if (distance > (npcCharacter.SightRangeNear)) { MoveTowardsPoint(destinationWayPoints[currentWaypointIndex], npcCharacter.MoveSpeed); } else if (distance > 0.25) { MoveTowardsPoint(destinationWayPoints[currentWaypointIndex], npcCharacter.MoveSpeed * 0.85f); } else { if (currentWaypointIndex == destinationWayPoints.GetUpperBound(0)) { // we have arrived at the final waypoint for this location isCurrentLocationExplored = true; npcCharacter.AddSearchedLocation(destination.SubjectID); // remember the location now that it is explored fully UnityEngine.Object[] scripts = FindObjectsOfType(typeof(LocationObjectScript)); LocationObjectScript inspectLocationScript = scripts.Single(o => (o as LocationObjectScript).Subject.SubjectID == destination.SubjectID) as LocationObjectScript; inspectLocationScript.TeachNpc(npcCharacter); npcCharacter.Inspect(inspectLocationScript.gameObject); destinationWayPoints = new Vector3[0]; destination = null; } else { currentWaypointIndex++; } } } } else if (chaseTarget != null) // chase the target { float distance = Vector3.Distance(chaseTarget.transform.position, transform.position); if (distance > 0.75) { MoveTowardsPoint(chaseTarget.transform.position, npcCharacter.MoveSpeed); } else { Vector3 targetDir = chaseTarget.transform.position - transform.position; transform.rotation = Quaternion.LookRotation(targetDir); chaseTarget = null; } } } else // this animal is dead { if (!isDead) //newly dead { Inventory.Add(new InventoryItem(DbIds.Meat, 5)); isDead = true; decaytime = 20.0f; } decaytime -= Time.deltaTime; UpdateDeadnessColor(); if (decaytime < 0) { Destroy(this.gameObject); } } // Debug: near vision range DrawDebugCircle(transform.position, npcCharacter.SightRangeNear, 20, new Color(0, 0, 1, 0.5f)); // Debug: far vision range DrawDebugCircle(transform.position, npcCharacter.SightRangeFar, 20, new Color(0, 0, 0, 0.3f)); }
/// <summary> /// Stop chasing a target. /// </summary> internal void ChaseStop() { chaseTarget = null; }
// Update is called once per frame void Update() { // ------------------------------------------------------------------------ // ------------------------ START CAMERA MOVEMENT ------------------------- // ------------------------------------------------------------------------ if (lastSelector != null) { cameraDestination = new Vector3(lastSelector.transform.position.x, cameraDestination.y, lastSelector.transform.position.z); } else if (Input.GetMouseButton(2)) { // panning camera float mouseY = Input.GetAxis("Mouse Y"); if (mouseY != 0) { cameraDestination = new Vector3(cameraDestination.x, cameraDestination.y, Camera.main.transform.position.z + mouseY * (cameraDestination.y / 25)); } float mouseX = Input.GetAxis("Mouse X"); if (mouseX != 0) { cameraDestination = new Vector3(Camera.main.transform.position.x + mouseX * (cameraDestination.y / 25), cameraDestination.y, cameraDestination.z); } } float mouseWheelDelta = Input.GetAxis("Mouse ScrollWheel"); if (mouseWheelDelta != 0) { Vector3 camPosition = Camera.main.transform.position; cameraDestination = new Vector3(camPosition.x, camPosition.y - mouseWheelDelta * (camPosition.y), Camera.main.transform.position.z); } if (Vector3.Distance(Camera.main.transform.position, cameraDestination) > 0.1f) { Camera.main.transform.position = Vector3.Slerp(Camera.main.transform.position, cameraDestination, Time.deltaTime * 20.0f); } // ------------------------------------------------------------------------ // ------------------------ END CAMERA MOVEMENT --------------------------- // ------------------------------------------------------------------------ if ((lastSelector != null) && (lastSelector.transform.parent != null)) { SubjectObjectScript script = lastSelector.transform.parent.GetComponent <SubjectObjectScript>() as SubjectObjectScript; _ID.text = "ID: <b>" + script.Subject.SubjectID.ToString() + "</b>"; _Name.text = "Name: <b>" + script.Subject.Name.ToString() + "</b>"; _Description.text = "Desc: <b>" + script.Subject.Description.ToString() + "</b>"; testPanel.SetActive(true); PlantSubject plantSub = script.Subject as PlantSubject; if (plantSub != null) { PlantObjectScript plantScript = script as PlantObjectScript; Subject produceSubject = masterSubjectList.GetSubject(plantSub.ProduceID); float maturePercent = Mathf.Min(plantScript.CurrentGrowth / plantSub.MatureGrowth, 1.0f); plantPanel.SetActive(true); animalPanel.SetActive(false); locationPanel.SetActive(false); _Produce.text = "Produce: <b>" + plantSub.ProduceID.ToString() + " - " + produceSubject.Name.ToString() + "</b>"; _Growth.text = "Growth: <b>" + plantScript.CurrentGrowth.ToString() + " / " + plantSub.MaxGrowth.ToString() + "</b>"; _Maturity.text = "Maturity: <b>" + maturePercent.ToString() + "</b>"; _Inventory.text = "Inventory: <b>" + plantScript.InventoryPercent().ToString() + "</b>"; } else { AnimalSubject animalSub = script.Subject as AnimalSubject; if (animalSub != null) { animalPanel.SetActive(true); plantPanel.SetActive(false); locationPanel.SetActive(false); AnimalObjectScript animalScript = script as AnimalObjectScript; _Health.text = "Health: <b>" + animalScript.GetHealth().ToString() + "</b>"; _Safety.text = "Safety: <b>" + animalScript.GetSafety().ToString() + "</b>"; _Food.text = "Food: <b>" + animalScript.GetFood().ToString() + "</b>"; } else { LocationSubject locationSub = script.Subject as LocationSubject; if (locationSub != null) { locationPanel.SetActive(true); plantPanel.SetActive(false); animalPanel.SetActive(false); _Center.text = "Center: <b>" + locationSub.Coordinates.ToString() + "</b>"; _Radius.text = "Radius: <b>" + locationSub.Radius.ToString() + "</b>"; } else { locationPanel.SetActive(false); plantPanel.SetActive(false); animalPanel.SetActive(false); } } } } else { //testPanel.SetActive(false); } //Place or use tool if (placeID < 1) { if (placeID < -1) //placeID == -2 { if (!IsOverMenu() && (Input.GetMouseButtonDown(0))) { centerPosition = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, Camera.main.transform.position.y)); SelectAtPosition(centerPosition, 0.4f); } } else if (placeID < 0) //placeID == -1 { //setting to Damage if (!IsOverMenu() && (Input.GetMouseButtonDown(0))) { centerPosition = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, Camera.main.transform.position.y)); if (HarmAtPosition(centerPosition, 1.0f)) { PopMessage("Kill!", centerPosition, 0); } } } else //placeID == 0 { //setting to delete objects if (!IsOverMenu() && (Input.GetMouseButtonDown(0))) { centerPosition = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, Camera.main.transform.position.y)); if (DeleteAtPosition(centerPosition, 1.0f)) { PopMessage("DELETED", centerPosition, 1); } } } } else // is placeable { if (!placementStarted) { //Since we have not started, we can look for our mouse for placement if (!IsOverMenu() && (Input.GetMouseButtonDown(0))) { //Set the center based on mouse position centerPosition = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, Camera.main.transform.position.y)); //We will let everything start with a radius of 0.5 if (CheckPlacementPosition(centerPosition, 0.5f, null)) { if (placeID == 2) //this is a location, which requires 2 steps { placedObject = Instantiate(locationStart, centerPosition, Quaternion.identity); //calculate our edge and manipulate the scale until finalized edgePosition = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, Camera.main.transform.position.y)); float distance = Vector3.Distance(centerPosition, edgePosition); if (CheckPlacementPosition(centerPosition, distance, placedObject)) { placedObject.transform.localScale = new Vector3(distance * 2, 0.1f, distance * 2); } placementStarted = true; } else { //Use the id to pull the Subject card Subject newSubject = masterSubjectList.GetSubject(placeID); if (newSubject != null) { placedObject = Instantiate(newSubject.Prefab, centerPosition, Quaternion.identity); if (placedObject != null) { SubjectObjectScript script = placedObject.GetComponent <SubjectObjectScript>() as SubjectObjectScript; script.InitializeFromSubject(masterSubjectList, newSubject); placementStarted = true; } } } } } } else { //We have started to place - is it a location? if (placeID == 2) { //calculate our edge and manipulate the scale until finalized edgePosition = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, Camera.main.transform.position.y)); float distance = Vector3.Distance(centerPosition, edgePosition); if (CheckPlacementPosition(centerPosition, distance, placedObject)) { placedObject.transform.localScale = new Vector3(distance * 2, 0.1f, distance * 2); lastDistance = distance; } //Look for a second mouse click to finalize the location //No more changes to distance if (!IsOverMenu() && (Input.GetMouseButtonDown(0))) { placementStarted = false; Destroy(placedObject); //get rid of our temp area //create a new location using the above values CreateLocation(centerPosition, lastDistance); } } else { //We can finalize everything else automatically placementStarted = false; } } } }
private void AiHunger() { // Get list of food in inventory InventoryItem foodItem = objectScript.Inventory.Take(new InventoryItem(foodID, 1)); if (foodItem.StackSize > 0) { // eat food in inventory Eat(foodItem); } else { // get list of all foodSource objects in near range // exclude objects we've already attempted harvesting from List <SubjectObjectScript> foodSource = considerObjects .Select(o => o.GetComponent <SubjectObjectScript>() as SubjectObjectScript) .Where(o => o.Subject.SubjectID == foodSourceID) .Where(o => !searchedObjects.Contains(o.GetInstanceID())).ToList(); // go to the first food source and harvest from it if (foodSource.Count > 0) { SubjectObjectScript foodSourceObject = foodSource[0]; // if it's within harvest range if (Vector3.Distance(foodSourceObject.transform.position, objectScript.transform.position) <= 1.0) { // we're within range, stop chasing objectScript.ChaseStop(); // Attempt to harvest from the food source InventoryItem harvestedItem = foodSourceObject.Harvest(); if (harvestedItem != null) { if (harvestedItem.StackSize > 0) { objectScript.Inventory.Add(harvestedItem); } else { // didn't get anything from this source searchedObjects.Add(foodSourceObject.GetInstanceID()); } } else // null means this is an animal that isn't dead, attack it. { AnimalObjectScript animal = foodSourceObject as AnimalObjectScript; animal.Damage(Subject, definition.AttackDamage, this); } } else //out of harvest range, chase this food source { objectScript.ChaseStart(foodSourceObject); } } else { // if we've searched all the locations we known of, start over. if (GetKnownLocationCount() == searchedLocations.Count && unexploredLocations.Count == 0) { searchedLocations.Clear(); searchedObjects.Clear(); } // there are no food sources in close range // find a location with foodSourceID List <LocationSubject> foodLocations = FindObject(db.GetSubject(foodSourceID), objectScript.transform.position, searchedLocations); if (foodLocations.Count > 0) { objectScript.MoveToNewLocation(foodLocations[0]); } else { AiExplore(); } } } }