/// <summary> /// Check visibility from this npc to the given npc /// </summary> /// <param name="npc">other npc on which is testing visibility</param> /// <returns>true if npc is visible, otherwise false</returns> /// <seealso cref="Bresenham"/> private bool CheckVisibility(IActing npc) { List <Point> line = Helper.Bresenham(this.GetPosition2D(), npc.GetStatus().position); List <int> heights = new List <int>(); int thisHeight = (int)Map.GetInstance().GetTerrain().Get3Dposition(this.GetPosition2D()).Y + 80; int npcHeight = (int)Map.GetInstance().GetTerrain().Get3Dposition(npc.GetStatus().position).Y + 80; foreach (Point p in line) { int height = (int)this.terrain.Get3Dposition(p).Y; if (Map.GetInstance().CellMap[p.X, p.Y].Block && !Map.GetInstance().CellMap[p.X, p.Y].Danger && !Map.GetInstance().CellMap[p.X, p.Y].Player) { height += 200; } heights.Add(height); } Vector3 npc1, npc2; npc2 = new Vector3(this.x, thisHeight, this.y); npc1 = new Vector3(npc.GetStatus().position.X, npcHeight, npc.GetStatus().position.Y); //Vector3 u = npc2 - npc1; //Vector3 n = Vector3.Cross(u, new Vector3(0,1,0)); float localHeight; for (int i = 0; i < line.Count; i++) { localHeight = npc1.Y + ((line[i].X - npc1.X) * (npc2.Y - npc1.Y)) / (npc2.X - npc1.X); //localHeight2 = npc1.Y + ((line[i].Y - npc1.Z) * (npc2.Y - npc1.Y)) / (npc2.Z - npc1.Z); if (localHeight < heights[i]) { //Logger.AddInfo(this.character.name + ": Nepritel " + npc.character.name + " neni videt"); return(false); } } return(true); }
/// <summary> /// from generated state-prob pairs choose the best one and returns new Confict state /// </summary> /// <param name="myself">npc, which is choosing from actions</param> /// <param name="enemy">enemy npc on which is the target</param> /// <param name="priors">priors from npc character, useless for now</param> /// <param name="actionType">type of action</param> /// <returns>new confict state</returns> public ConflictState GetNextAction(IActing myself, IActing enemy, Priorities priors, out Action selectedAction) { ConflictState currentState = new ConflictState(myself.GetStatus(), enemy.GetStatus()); Priorities priorities = priors; CharacterNPC myChar = myself.GetCharacter(); //if (this.stateSpace.Count == 0) //{ // CreateStateSpace(currentState, myChar); //} List <StateProbPairs> expanders = Expand(currentState, myChar); StateProbPairs result = new StateProbPairs(); int lowestCost = int.MaxValue; int actionCost = int.MaxValue; foreach (StateProbPairs pairs in expanders) { //if (this.stateSpace.Contains(pairs)) //{ // Logging.Logger.AddInfo(pairs.ToString() + " je obsazeno"); //} actionCost = ComputeCost(currentState, pairs, myChar); if (actionCost < lowestCost && actionCost >= 0) { result = pairs; lowestCost = actionCost; } } if (result.states == null) { result.states.Add(currentState); Action empty = new Action(); empty.name = "empty"; empty.time = 5000; result.action = empty; result.probabilities.Add(100); } int index = 0; if (result.probabilities.Count > 1) { int randChoose = rand.Next(100); if (randChoose < result.probabilities[0]) { index = 0; } else if (randChoose < result.probabilities[0] + result.probabilities[1]) { index = 1; } else { if (result.states.Count > 2) { index = 2; } } } if (index >= result.states.Count) { index = 0; } Logging.Logger.AddInfo(myChar.name + ": " + result.action.ToString() + " proti " + enemy.GetCharacter().name + ", cost=" + lowestCost + ", efekt: " + index); myself.SetCoolDown(result.action.time); selectedAction = result.action; this.lastAction = selectedAction; //return result.states[index]; return(result.states[0]); }
/// <summary> /// ctor, create info about NPC /// </summary> /// <param name="npc"></param> public NpcInfo(IActing npc) { this.status = npc.GetStatus(); this.character = npc.GetCharacter(); }
public ConflictState GetNextAction(IActing myself, IActing enemy, Priorities priors, out Action selectedAction) { //TODO dodelat selectedAction = this.attackActions[0]; return(new ConflictState(myself.GetStatus(), enemy.GetStatus())); }
/// <summary> /// NPC is attacked by unseen attacker /// </summary> /// <param name="enemy"></param> public void RegisterAttack(IActing enemy) { this.TargetedEnemy = enemy; }
/// <summary> /// update NPC's map, check if is anybody in visual range /// </summary> /// <param name="npcs">list of all npcs</param> /// <param name="step">duration from last update in miliseconds, typicaly little part of second</param> public void UpdateNPC(List <NPC> npcs, float step) { if (!this.currentStatus.alive || this.currentStatus.hp <= 0) { return; } UpdateTime(step); UpdateTask(); #region check npcs and player int seenEnemyCount = 0; int nearest = this.visualRange + 1000; int distance; this.currentStatus.nearEnemies.Clear(); //check npcs if (npcs.Count > 1) //if only one NPC -> this one { foreach (NPC npc in npcs) { if (this.character.type == NPCType.villager) { this.controlMechanism.Update(); return; } else if (this.character.type == NPCType.guard) { //guards will atack only player break; } else if (this.Equals(npc)) { continue; //this npc } else if (npc.character.type == NPCType.villager || npc.character.type == NPCType.boss || npc.character.type == NPCType.guard) { //don't attack villagers and guards and boss continue; } else if (this.character.type == npc.character.type && npc.character.type != NPCType.enemy) { //not enemy continue; } distance = CalculateDistance(npc.GetPosition2D()); if (distance < this.visualRange && CheckVisibility(npc)) { seenEnemyCount++; this.currentStatus.nearEnemies.Add(npc); if (distance < nearest) //TODO lip vybirat target { this.targetedEnemy = npc; nearest = distance; } } } } //check player if (CanAttackPlayer) { distance = CalculateDistance(this.terrain.GetPlayerPosition()); if (distance < this.visualRange && CheckVisibility(GamePlayer.GetPlayer())) { IActing player = GamePlayer.GetPlayer(); seenEnemyCount++; this.currentStatus.nearEnemies.Add(GamePlayer.GetPlayer()); if (distance < nearest) { this.targetedEnemy = GamePlayer.GetPlayer(); nearest = distance; } } } #endregion int targetingEnemyPower = 0; foreach (IActing npc in this.currentStatus.nearEnemies) { if (npc.GetTargetedEnemy() == (this as IActing)) { targetingEnemyPower += ((int)npc.GetStatus().hp *npc.GetCharacter().level); } } //update status this.currentStatus.enemySeen = seenEnemyCount; this.currentStatus.enemyPower = targetingEnemyPower; this.currentStatus.position = this.GetPosition2D(); this.currentStatus.cooldown = this.cooldown; this.controlMechanism.Update(); this.step = step; }
public void Dispose() { this.targetedEnemy = null; this.taskStack = null; this.pathFinding = null; }