Peek into the AI for some battle insights.
More detailed violence
We can watch the NPCs take damage and eventually expire, but it’s not exactly super-clear where the damage is coming from. If we poke into the server code to see what’s going on:
DragonsSpine/GameObjects/GameLiving/NPC/AI/AI.cs GitLab
2641
Command.ParseCommand(npc, "poke" , npc.mostHated.Name);
DragonsSpine/GameObjects/GameLiving/NPC/AI/AI.cs GitLab
2647
Command.ParseCommand(npc, "shoot" , npc.mostHated.Name);
DragonsSpine/GameObjects/GameLiving/NPC/AI/AI.cs GitLab
2662
Command.ParseCommand(npc, "kick" , npc.mostHated.Name);
DragonsSpine/GameObjects/GameLiving/NPC/AI/AI.cs GitLab
2666
Command.ParseCommand(npc, "kill" , npc.mostHated.Name);
DragonsSpine/GameObjects/GameLiving/NPC/AI/AI.cs GitLab
2674
Command.ParseCommand(npc, "jumpkick" , npc.mostHated.Name + "/Ki Yah!/!" );
Ok, I think we see a pattern. If we know the NPC’s mostHated
, we can be pretty sure that’s who the NPC is attacking. Luckily we’ve already added it to the LiveNPC
table in the database, so it’s just a matter of
surfacing it.
Assets/DragonsSpine/DAL/DBNPC.cs GitLab
127
128
129
130
npc.hasMostHated = !(dr.IsNull(dtNPCs.Columns["mostHatedId" ]));
if (npc.hasMostHated) {
npc.mostHatedId = Convert.ToInt32(dr["mostHatedId" ]);
}
Assets/Managers/NpcManager.cs GitLab
129
130
npcScripts[npc.worldNpcID].hasMostHated = npc.hasMostHated;
npcScripts[npc.worldNpcID].mostHatedId = npc.mostHatedId;
Then we make an angry red arrow to point at the object of most hatred:
Wow what a hateful arrow.
We need a way to find the position of our foe:
Assets/Managers/NpcManager.cs GitLab
174
175
176
177
178
179
public Vector3 locateNpc(int npcId) {
if (npcScripts.ContainsKey(npcId))
return npcScripts[npcId].transform.position;
else
return Vector3.zero;
}
And now we can display our hatred:
Assets/NpcScript.cs GitLab
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// display hatred
if (hasMostHated) {
if (myHatred == null ) {
myHatred = Instantiate(hatredPrefab,
Vector3.zero,
Quaternion.identity) as Transform;
myHatred.parent = this .transform;
myHatred.localPosition = new Vector3(0f , 0f , 0.2f );
myHatredRend = myHatred.GetComponent<Renderer>();
}
hatedLocation = npcManager.locateNpc(mostHatedId);
Vector3 hatredDir = hatedLocation - transform.position;
hatredDir.z = 0f ;
hatredDir = hatredDir.normalized;
Quaternion qDir = new Quaternion();
qDir.SetLookRotation(hatredDir, new Vector3(0f , 0f , 1f ));
myHatred.rotation = qDir;
myHatred.localScale = new Vector3(0.3f , 1f , 1f );
myHatredRend.enabled = toBeSeen;
} else {
if (myHatred != null ) {
myHatredRend.enabled = false ;
}
}
Lots of hating going on in the temple today
Cohatred
That’s cool, but the Update
method in NpcScript
is getting crowded. Can’t we do this in
a cool, coroutine-ish way ?
Assets/NpcScript.cs GitLab
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public bool HasMostHated {
get { return hasMostHated; }
set {
if (hasMostHated != value ) {
hasMostHated = value ;
StopCoroutine("Hatred" );
StartCoroutine("Hatred" );
}
}
}
public int MostHatedId {
get { return mostHatedId; }
set {
if (mostHatedId != value ) {
mostHatedId = value ;
StopCoroutine("Hatred" );
StartCoroutine("Hatred" );
}
}
}
Assets/NpcScript.cs GitLab
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
IEnumerator Hatred () {
while (hasMostHated && !presumedDead && hits > 0f ) {
if (myHatred == null ) {
myHatred = Instantiate(hatredPrefab,
Vector3.zero,
Quaternion.identity) as Transform;
myHatred.parent = this .transform;
myHatred.localPosition = new Vector3(0f , 0f , 0.2f );
myHatredRend = myHatred.GetComponent<Renderer>();
}
hatedLocation = npcManager.locateNpc(mostHatedId);
Vector3 hatredDir = hatedLocation - transform.position;
hatredDir.z = 0f ;
hatredDir = hatredDir.normalized;
Quaternion qDir = new Quaternion();
qDir.SetLookRotation(hatredDir, new Vector3(0f , 0f , 1f ));
myHatred.rotation = qDir;
myHatred.localScale = new Vector3(0.3f , 0.1f , 1f );
Vector3 startPos = transform.position + hatredDir * transform.localScale.x * 0.5f ;
Vector3 endPos = hatedLocation - hatredDir * transform.localScale.x * 0.5f ;
startPos.z += 0.2f ; endPos.z += 0.2f ;
myHatred.position = Vector3.Lerp(startPos, endPos, Time.time % 1f );
myHatredRend.enabled = toBeSeen;
yield return null ;
}
if (myHatred != null ) {
myHatredRend.enabled = false ;
}
}
And while we’re at it, we take advantage of the added efficiency to animate the arrows a bit.
Look how popular the priest is!
Day 18 code - client