Core/BattlePets: Add battle pets to pet journal when learning related spells

This commit is contained in:
hondacrx
2017-12-04 14:32:40 -05:00
parent b017ef8e84
commit f6d86328f9
2 changed files with 298 additions and 277 deletions
+286 -277
View File
@@ -41,281 +41,6 @@ namespace Game.Collision
tree.Add(0); tree.Add(0);
} }
public void build<T>(List<T> primitives, uint leafSize = 3, bool printStats = false) where T : IModel
{
if (primitives.Count == 0)
{
init_empty();
return;
}
buildData dat;
dat.maxPrims = (int)leafSize;
dat.numPrims = (uint)primitives.Count;
dat.indices = new uint[dat.numPrims];
dat.primBound = new AxisAlignedBox[dat.numPrims];
bounds = primitives[0].getBounds();
for (int i = 0; i < dat.numPrims; ++i)
{
dat.indices[i] = (uint)i;
dat.primBound[i] = primitives[i].getBounds();
bounds.merge(dat.primBound[i]);
}
List<uint> tempTree = new List<uint>();
BuildStats stats = new BuildStats();
buildHierarchy(tempTree, dat, stats);
if (printStats)
stats.printStats();
for (int i = 0; i < dat.numPrims; ++i)
objects.Add(dat.indices[i]);
tree = tempTree;
}
public uint primCount() { return (uint)objects.Count; }
public bool readFromFile(BinaryReader reader)
{
var lo = reader.ReadStruct<Vector3>();
var hi = reader.ReadStruct<Vector3>();
bounds = new AxisAlignedBox(lo, hi);
uint treeSize = reader.ReadUInt32();
tree.Clear();
for (var i = 0; i < treeSize; i++)
tree.Add(reader.ReadUInt32());
var count = reader.ReadUInt32();
objects.Clear();
for (var i = 0; i < count; i++)
objects.Add(reader.ReadUInt32());
return true;
}
public void intersectRay(Ray r, WorkerCallback intersectCallback, ref float maxDist, bool stopAtFirst = false)
{
float intervalMin = -1.0f;
float intervalMax = -1.0f;
Vector3 org = r.Origin;
Vector3 dir = r.Direction;
Vector3 invDir = new Vector3();
for (int i = 0; i < 3; ++i)
{
invDir[i] = 1.0f / dir[i];
if (MathFunctions.fuzzyNe(dir[i], 0.0f))
{
float t1 = (bounds.Lo[i] - org[i]) * invDir[i];
float t2 = (bounds.Hi[i] - org[i]) * invDir[i];
if (t1 > t2)
MathFunctions.Swap<float>(ref t1, ref t2);
if (t1 > intervalMin)
intervalMin = t1;
if (t2 < intervalMax || intervalMax < 0.0f)
intervalMax = t2;
// intervalMax can only become smaller for other axis,
// and intervalMin only larger respectively, so stop early
if (intervalMax <= 0 || intervalMin >= maxDist)
return;
}
}
if (intervalMin > intervalMax)
return;
intervalMin = Math.Max(intervalMin, 0.0f);
intervalMax = Math.Min(intervalMax, maxDist);
uint[] offsetFront = new uint[3];
uint[] offsetBack = new uint[3];
uint[] offsetFront3 = new uint[3];
uint[] offsetBack3 = new uint[3];
// compute custom offsets from direction sign bit
for (int i = 0; i < 3; ++i)
{
offsetFront[i] = floatToRawIntBits(dir[i]) >> 31;
offsetBack[i] = offsetFront[i] ^ 1;
offsetFront3[i] = offsetFront[i] * 3;
offsetBack3[i] = offsetBack[i] * 3;
// avoid always adding 1 during the inner loop
++offsetFront[i];
++offsetBack[i];
}
StackNode[] stack = new StackNode[64];
int stackPos = 0;
int node = 0;
while (true)
{
while (true)
{
uint tn = tree[node];
uint axis = (uint)(tn & (3 << 30)) >> 30;
bool BVH2 = Convert.ToBoolean(tn & (1 << 29));
int offset = (int)(tn & ~(7 << 29));
if (!BVH2)
{
if (axis < 3)
{
// "normal" interior node
float tf = (intBitsToFloat(tree[(int)(node + offsetFront[axis])]) - org[axis]) * invDir[axis];
float tb = (intBitsToFloat(tree[(int)(node + offsetBack[axis])]) - org[axis]) * invDir[axis];
// ray passes between clip zones
if (tf < intervalMin && tb > intervalMax)
break;
int back = (int)(offset + offsetBack3[axis]);
node = back;
// ray passes through far node only
if (tf < intervalMin)
{
intervalMin = (tb >= intervalMin) ? tb : intervalMin;
continue;
}
node = offset + (int)offsetFront3[axis]; // front
// ray passes through near node only
if (tb > intervalMax)
{
intervalMax = (tf <= intervalMax) ? tf : intervalMax;
continue;
}
// ray passes through both nodes
// push back node
stack[stackPos].node = (uint)back;
stack[stackPos].tnear = (tb >= intervalMin) ? tb : intervalMin;
stack[stackPos].tfar = intervalMax;
stackPos++;
// update ray interval for front node
intervalMax = (tf <= intervalMax) ? tf : intervalMax;
continue;
}
else
{
// leaf - test some objects
int n = (int)tree[node + 1];
while (n > 0)
{
bool hit = intersectCallback.Invoke(r, objects[offset], ref maxDist, stopAtFirst);
if (stopAtFirst && hit)
return;
--n;
++offset;
}
break;
}
}
else
{
if (axis > 2)
return; // should not happen
float tf = (intBitsToFloat(tree[(int)(node + offsetFront[axis])]) - org[axis]) * invDir[axis];
float tb = (intBitsToFloat(tree[(int)(node + offsetBack[axis])]) - org[axis]) * invDir[axis];
node = offset;
intervalMin = (tf >= intervalMin) ? tf : intervalMin;
intervalMax = (tb <= intervalMax) ? tb : intervalMax;
if (intervalMin > intervalMax)
break;
continue;
}
} // traversal loop
do
{
// stack is empty?
if (stackPos == 0)
return;
// move back up the stack
stackPos--;
intervalMin = stack[stackPos].tnear;
if (maxDist < intervalMin)
continue;
node = (int)stack[stackPos].node;
intervalMax = stack[stackPos].tfar;
break;
} while (true);
}
}
public void intersectPoint(Vector3 p, WorkerCallback intersectCallback)
{
if (!bounds.contains(p))
return;
StackNode[] stack = new StackNode[64];
int stackPos = 0;
int node = 0;
while (true)
{
while (true)
{
uint tn = tree[node];
uint axis = (uint)(tn & (3 << 30)) >> 30;
bool BVH2 = Convert.ToBoolean(tn & (1 << 29));
int offset = (int)(tn & ~(7 << 29));
if (!BVH2)
{
if (axis < 3)
{
// "normal" interior node
float tl = intBitsToFloat(tree[node + 1]);
float tr = intBitsToFloat(tree[node + 2]);
// point is between clip zones
if (tl < p[(int)axis] && tr > p[axis])
break;
int right = offset + 3;
node = right;
// point is in right node only
if (tl < p[(int)axis])
{
continue;
}
node = offset; // left
// point is in left node only
if (tr > p[axis])
{
continue;
}
// point is in both nodes
// push back right node
stack[stackPos].node = (uint)right;
stackPos++;
continue;
}
else
{
// leaf - test some objects
uint n = tree[node + 1];
while (n > 0)
{
intersectCallback.Invoke(p, objects[offset]); // !!!
--n;
++offset;
}
break;
}
}
else // BVH2 node (empty space cut off left and right)
{
if (axis > 2)
return; // should not happen
float tl = intBitsToFloat(tree[node + 1]);
float tr = intBitsToFloat(tree[node + 2]);
node = offset;
if (tl > p[axis] || tr < p[axis])
break;
continue;
}
} // traversal loop
// stack is empty?
if (stackPos == 0)
return;
// move back up the stack
stackPos--;
node = (int)stack[stackPos].node;
}
}
void buildHierarchy(List<uint> tempTree, buildData dat, BuildStats stats) void buildHierarchy(List<uint> tempTree, buildData dat, BuildStats stats)
{ {
// create space for the first node // create space for the first node
@@ -546,6 +271,280 @@ namespace Game.Collision
stats.updateLeaf(depth + 1, 0); stats.updateLeaf(depth + 1, 0);
} }
public bool readFromFile(BinaryReader reader)
{
var lo = reader.ReadStruct<Vector3>();
var hi = reader.ReadStruct<Vector3>();
bounds = new AxisAlignedBox(lo, hi);
uint treeSize = reader.ReadUInt32();
tree.Clear();
for (var i = 0; i < treeSize; i++)
tree.Add(reader.ReadUInt32());
var count = reader.ReadUInt32();
objects.Clear();
for (var i = 0; i < count; i++)
objects.Add(reader.ReadUInt32());
return true;
}
public void build<T>(List<T> primitives, uint leafSize = 3, bool printStats = false) where T : IModel
{
if (primitives.Count == 0)
{
init_empty();
return;
}
buildData dat;
dat.maxPrims = (int)leafSize;
dat.numPrims = (uint)primitives.Count;
dat.indices = new uint[dat.numPrims];
dat.primBound = new AxisAlignedBox[dat.numPrims];
bounds = primitives[0].getBounds();
for (int i = 0; i < dat.numPrims; ++i)
{
dat.indices[i] = (uint)i;
dat.primBound[i] = primitives[i].getBounds();
bounds.merge(dat.primBound[i]);
}
List<uint> tempTree = new List<uint>();
BuildStats stats = new BuildStats();
buildHierarchy(tempTree, dat, stats);
for (int i = 0; i < dat.numPrims; ++i)
objects.Add(dat.indices[i]);
tree = tempTree;
}
public uint primCount() { return (uint)objects.Count; }
public void intersectRay(Ray r, WorkerCallback intersectCallback, ref float maxDist, bool stopAtFirst = false)
{
float intervalMin = -1.0f;
float intervalMax = -1.0f;
Vector3 org = r.Origin;
Vector3 dir = r.Direction;
Vector3 invDir = new Vector3();
for (int i = 0; i < 3; ++i)
{
invDir[i] = 1.0f / dir[i];
if (MathFunctions.fuzzyNe(dir[i], 0.0f))
{
float t1 = (bounds.Lo[i] - org[i]) * invDir[i];
float t2 = (bounds.Hi[i] - org[i]) * invDir[i];
if (t1 > t2)
MathFunctions.Swap<float>(ref t1, ref t2);
if (t1 > intervalMin)
intervalMin = t1;
if (t2 < intervalMax || intervalMax < 0.0f)
intervalMax = t2;
// intervalMax can only become smaller for other axis,
// and intervalMin only larger respectively, so stop early
if (intervalMax <= 0 || intervalMin >= maxDist)
return;
}
}
if (intervalMin > intervalMax)
return;
intervalMin = Math.Max(intervalMin, 0.0f);
intervalMax = Math.Min(intervalMax, maxDist);
uint[] offsetFront = new uint[3];
uint[] offsetBack = new uint[3];
uint[] offsetFront3 = new uint[3];
uint[] offsetBack3 = new uint[3];
// compute custom offsets from direction sign bit
for (int i = 0; i < 3; ++i)
{
offsetFront[i] = floatToRawIntBits(dir[i]) >> 31;
offsetBack[i] = offsetFront[i] ^ 1;
offsetFront3[i] = offsetFront[i] * 3;
offsetBack3[i] = offsetBack[i] * 3;
// avoid always adding 1 during the inner loop
++offsetFront[i];
++offsetBack[i];
}
StackNode[] stack = new StackNode[64];
int stackPos = 0;
int node = 0;
while (true)
{
while (true)
{
uint tn = tree[node];
uint axis = (uint)(tn & (3 << 30)) >> 30;
bool BVH2 = Convert.ToBoolean(tn & (1 << 29));
int offset = (int)(tn & ~(7 << 29));
if (!BVH2)
{
if (axis < 3)
{
// "normal" interior node
float tf = (intBitsToFloat(tree[(int)(node + offsetFront[axis])]) - org[axis]) * invDir[axis];
float tb = (intBitsToFloat(tree[(int)(node + offsetBack[axis])]) - org[axis]) * invDir[axis];
// ray passes between clip zones
if (tf < intervalMin && tb > intervalMax)
break;
int back = (int)(offset + offsetBack3[axis]);
node = back;
// ray passes through far node only
if (tf < intervalMin)
{
intervalMin = (tb >= intervalMin) ? tb : intervalMin;
continue;
}
node = offset + (int)offsetFront3[axis]; // front
// ray passes through near node only
if (tb > intervalMax)
{
intervalMax = (tf <= intervalMax) ? tf : intervalMax;
continue;
}
// ray passes through both nodes
// push back node
stack[stackPos].node = (uint)back;
stack[stackPos].tnear = (tb >= intervalMin) ? tb : intervalMin;
stack[stackPos].tfar = intervalMax;
stackPos++;
// update ray interval for front node
intervalMax = (tf <= intervalMax) ? tf : intervalMax;
continue;
}
else
{
// leaf - test some objects
int n = (int)tree[node + 1];
while (n > 0)
{
bool hit = intersectCallback.Invoke(r, objects[offset], ref maxDist, stopAtFirst);
if (stopAtFirst && hit)
return;
--n;
++offset;
}
break;
}
}
else
{
if (axis > 2)
return; // should not happen
float tf = (intBitsToFloat(tree[(int)(node + offsetFront[axis])]) - org[axis]) * invDir[axis];
float tb = (intBitsToFloat(tree[(int)(node + offsetBack[axis])]) - org[axis]) * invDir[axis];
node = offset;
intervalMin = (tf >= intervalMin) ? tf : intervalMin;
intervalMax = (tb <= intervalMax) ? tb : intervalMax;
if (intervalMin > intervalMax)
break;
continue;
}
} // traversal loop
do
{
// stack is empty?
if (stackPos == 0)
return;
// move back up the stack
stackPos--;
intervalMin = stack[stackPos].tnear;
if (maxDist < intervalMin)
continue;
node = (int)stack[stackPos].node;
intervalMax = stack[stackPos].tfar;
break;
} while (true);
}
}
public void intersectPoint(Vector3 p, WorkerCallback intersectCallback)
{
if (!bounds.contains(p))
return;
StackNode[] stack = new StackNode[64];
int stackPos = 0;
int node = 0;
while (true)
{
while (true)
{
uint tn = tree[node];
uint axis = (uint)(tn & (3 << 30)) >> 30;
bool BVH2 = Convert.ToBoolean(tn & (1 << 29));
int offset = (int)(tn & ~(7 << 29));
if (!BVH2)
{
if (axis < 3)
{
// "normal" interior node
float tl = intBitsToFloat(tree[node + 1]);
float tr = intBitsToFloat(tree[node + 2]);
// point is between clip zones
if (tl < p[(int)axis] && tr > p[axis])
break;
int right = offset + 3;
node = right;
// point is in right node only
if (tl < p[(int)axis])
{
continue;
}
node = offset; // left
// point is in left node only
if (tr > p[axis])
{
continue;
}
// point is in both nodes
// push back right node
stack[stackPos].node = (uint)right;
stackPos++;
continue;
}
else
{
// leaf - test some objects
uint n = tree[node + 1];
while (n > 0)
{
intersectCallback.Invoke(p, objects[offset]); // !!!
--n;
++offset;
}
break;
}
}
else // BVH2 node (empty space cut off left and right)
{
if (axis > 2)
return; // should not happen
float tl = intBitsToFloat(tree[node + 1]);
float tr = intBitsToFloat(tree[node + 2]);
node = offset;
if (tl > p[axis] || tr < p[axis])
break;
continue;
}
} // traversal loop
// stack is empty?
if (stackPos == 0)
return;
// move back up the stack
stackPos--;
node = (int)stack[stackPos].node;
}
}
void createNode(List<uint> tempTree, int nodeIndex, int left, int right) void createNode(List<uint> tempTree, int nodeIndex, int left, int right)
{ {
// write leaf node // write leaf node
@@ -597,8 +596,18 @@ namespace Game.Collision
public void updateInner() { numNodes++; } public void updateInner() { numNodes++; }
public void updateBVH2() { numBVH2++; } public void updateBVH2() { numBVH2++; }
public void updateLeaf(int depth, int n) { } public void updateLeaf(int depth, int n)
public void printStats() { } {
numLeaves++;
minDepth = Math.Min(depth, minDepth);
maxDepth = Math.Max(depth, maxDepth);
sumDepth += depth;
minObjects = Math.Min(n, minObjects);
maxObjects = Math.Max(n, maxObjects);
sumObjects += n;
int nl = Math.Min(n, 5);
++numLeavesN[nl];
}
} }
@@ -22,6 +22,7 @@ using Game.Network.Packets;
using Game.Spells; using Game.Spells;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Game.BattlePets;
namespace Game.Entities namespace Game.Entities
{ {
@@ -2520,6 +2521,17 @@ namespace Game.Entities
if (Global.DB2Mgr.GetMount(spellId) != null) if (Global.DB2Mgr.GetMount(spellId) != null)
GetSession().GetCollectionMgr().AddMount(spellId, MountStatusFlags.None, false, IsInWorld ? false : true); GetSession().GetCollectionMgr().AddMount(spellId, MountStatusFlags.None, false, IsInWorld ? false : true);
// need to add Battle pets automatically into pet journal
foreach (BattlePetSpeciesRecord entry in CliDB.BattlePetSpeciesStorage.Values)
{
if (entry.SummonSpellID == spellId && GetSession().GetBattlePetMgr().GetPetCount(entry.Id) == 0)
{
GetSession().GetBattlePetMgr().AddPet(entry.Id, entry.CreatureID, BattlePetMgr.RollPetBreed(entry.Id), BattlePetMgr.GetDefaultPetQuality(entry.Id));
UpdateCriteria(CriteriaTypes.OwnBattlePetCount);
break;
}
}
// return true (for send learn packet) only if spell active (in case ranked spells) and not replace old spell // return true (for send learn packet) only if spell active (in case ranked spells) and not replace old spell
return active && !disabled && !superceded_old; return active && !disabled && !superceded_old;
} }