public void DisplayAction(Vector3 where, GOAPAct action, Color textColor, string subText = "") { string text = ActionToText(action, action.ActionLayer) + " " + LayerToText(action.ActionLayer) + " " + LayerToText(action.ActionLayer2) + subText; textColor = ActionToColor(action); PopUp(where, text, textColor); }
protected virtual void GetPlan() { if (alive) { CurrentAction = null; toDo = planner.MakePlan(this, GetCurrentState(), HungryCheck()); if (toDo == null || toDo.Count == 0) //if failed to find a plan or plan has no moves { if (manager.debug) { Debug.Log("toDo was null"); } if (HeldItem != null) //if holding item is preventing you finding a path or actions, let's try dropping the item { DropItem(); } Invoke("Idle", breakTime * Random.Range(1f, 2f)); } else { if (manager.debug) { Debug.Log(toDo.Peek()); } GetDecision(); } } }
public Node(Node parent, float costBenefit, List <GameState.State> goalState, GOAPAct action) { this.parent = parent; this.costBenefit = costBenefit; this.goalState = goalState; this.action = action; }
string ActionToText(GOAPAct action, int layer) { string text = ""; if (action is Eat) { text = "Ate"; } if (action is Follow) { text = "Following"; } if (action is MeleeAttack) { if (layer == 11 || layer == 12 || layer == 13 || layer == 14) { text = "Attacked"; } else { text = "Harvested (" + action.ActionSkill.ToString("F2") + ")"; } } if (action is PickupItem) { text = "Picked Up"; } if (action is ThrowItem) { text = "Threw"; } return(text); }
//you can eat anything you can pick up. and that will be taught to buddies. public void EatItem() { if (HeldItem != null) { CurrentAction = new Eat(HeldItem.layer); if (CurrentAction.PerformEvent(this)) { if (teaching) { OnTeach(); } //tutorial shit if (manager.Tutorial) { if (manager.tut.Tut2EatBerry) { manager.tut.Tut2EatBerry = false; manager.tut.Tut3HardMelee = true; manager.tut.DisplayNextTip(3);//hit bush well manager.tut.SpawnBush(); } else { manager.tut.SpawnBush(); } } //end tutorial shit } } }
public void LearnFromAI() { //select a teacher (using queue instead of rando so we get a healthy balance of peeps) CreatureLogic learnFrom = null; while (learnFrom == null) { learnFrom = manager.spawner.Teachers.Dequeue(); } manager.spawner.Teachers.Enqueue(learnFrom); foreach (GOAPAct act in learnFrom.availableActions) { if (!IsDupeAction(act)) { availableActions.Add(act.Clone()); } } //learn one more random action from a random AI just to keep it spicy int teacher = UnityEngine.Random.Range(0, manager.spawner.ActiveBuddies.Count); CreatureLogic randoTeacher = manager.spawner.ActiveBuddies[teacher].GetComponent <CreatureLogic>(); if (randoTeacher != null && randoTeacher.availableActions.Count > 0) { GOAPAct a = randoTeacher.availableActions[UnityEngine.Random.Range(0, randoTeacher.availableActions.Count)]; availableActions.Add(a); } else { LearnRandomSkills(); return; } SetGoals(); }
//every buddy by default know how to eat at low efficiency but if they are taught that action again //they will overwrite their default action with what they were taught (its how they can improve with better teaching) void ImproveCoreHarvestSkill(GOAPAct newActions) { MeleeAttack hitBush = new MeleeAttack(6, 1); if (newActions.GetType() == hitBush.GetType()) { if (newActions.ActionLayer == hitBush.ActionLayer && newActions.ActionLayer2 == hitBush.ActionLayer2) { availableActions[2] = newActions; } } }
//throwing an item is determined by where the mouse is public void ThrowItem() { Vector3 mousePos = control.MousePos(); //get mouse position int targetLayer = control.ThrowingTarget(mousePos); //get what is at the mouse position //note, mousePos isn't actually used yet. I thought about teaching buddies to throw to a specific position throw RELATIVE to the cow for example //but unnecessary ThrowItem throwItem = new ThrowItem(mousePos, HeldItem.layer, control.ThrowingTarget(mousePos)); CurrentAction = throwItem; if (CurrentAction.PerformEvent(this)) { if (teaching) { OnTeach(); } } }
public override void PickUp(IThrowable item) { base.PickUp(item); PickupItem pickup = new PickupItem(item.ThisGameObject().layer); CurrentAction = pickup; if (teaching) { OnTeach(); } //tutorial shit if (manager.Tutorial && manager.tut.Tut1PickupBerry) { manager.tut.Tut1PickupBerry = false; manager.tut.Tut2EatBerry = true; manager.tut.DisplayNextTip(2);//eat the berry } //end tutorial shit }
bool IsDupeAction(GOAPAct newAction) //checks if I know this already { foreach (var act in availableActions) { if (newAction.GetType() == act.GetType()) { if (act.ActionLayer == newAction.ActionLayer && act.ActionLayer2 == newAction.ActionLayer2) { learningActions--;//buddy was taught a dupe, expending a learning opportunity if (manager.PlayerAlive) { ImproveCoreHarvestSkill(newAction); manager.ui.DisplayAction(transform.position, newAction, Color.white, "<br><size=6>(" + (learningActions - availableActions.Count).ToString() + " left)"); } return(true); } } } return(false); }
//checks if agent's motives match what action aims to achieve float checkGoalAlignment(Buddy agent, GOAPAct action) { float alignmentScore = 0; if (agent.motiveReproduction > 0 && action.motiveReproduction > 0) { alignmentScore += agent.motiveReproduction; } if (agent.motiveHarvest > 0 && action.motiveHarvest > 0) { alignmentScore += agent.motiveHarvest; } if (agent.motiveAttack > 0 && action.motiveAttack > 0) { alignmentScore += agent.motiveAttack; } if (agent.motiveHelper > 0 && action.motiveHelper > 0) { alignmentScore += agent.motiveHelper; } return(alignmentScore); }
//returns the best action to take depending on current game state, as well as a queue of actions to perform after that //ideally this should take the game state when deciding, instead of just randomly choosing from possibleEvents protected virtual void GetDecision() { CurrentAction = null; if (Target != null && !Target.activeSelf) //if somehow target became inactive, set it to null { if (manager.debug) { Debug.Log("target set to null"); } ClearTarget(); } if (toDo != null && toDo.Count > 0)//if we still got things we wanna peform { CurrentAction = toDo.Dequeue(); PerformDecision(); } else { GetPlan(); } }
Color ActionToColor(GOAPAct action) { Color textColor = Color.white; float[] motives = new float[] { action.motiveAttack, action.motiveHarvest, action.motiveReproduction, action.motiveHelper }; Array.Sort(motives); if (motives[motives.Length - 1] == action.motiveAttack) { textColor = manager.HeadColor.Evaluate(0.5f); } if (motives[motives.Length - 1] == action.motiveHarvest) { textColor = manager.HeadColor.Evaluate(0.25f); } if (motives[motives.Length - 1] == action.motiveReproduction) { textColor = manager.HeadColor.Evaluate(0.7f); } if (motives[motives.Length - 1] == action.motiveHelper) { textColor = manager.HeadColor.Evaluate(1f); } return(textColor); }
public void MeleeAttack() { MeleeAttack melee = new MeleeAttack(Target.gameObject.layer, bobHeight); CurrentAction = melee; //prior event should be destroyed by GC i think? if (melee.CheckPreconditions(GetCurrentState())) //if this can be performed { if (melee.PerformEvent(this)) //perform it { if (teaching) //and if you're teaching someone { OnTeach(); //broadcast the teaching event } //tutorial shit if (manager.Tutorial && manager.tut.Tut0WASD) { manager.tut.Tut0WASD = false; manager.tut.Tut1PickupBerry = true; manager.tut.DisplayNextTip(1);//pickup the berry } //end tutorial shit } } }