Updated Copyright year to 2013
[getmangos.git] / src / game / movement / packet_builder.cpp
blob2242a3447cac4e13f8c4c30cec511be2ba6ae4da
1 /*
2 * Copyright (C) 2005-2013 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "packet_builder.h"
20 #include "MoveSpline.h"
21 #include "Util.h"
22 #include "WorldPacket.h"
23 #include "../Creature.h"
25 namespace Movement
27 inline void operator << (ByteBuffer& b, const Vector3& v)
29 b << v.x << v.y << v.z;
32 inline void operator >> (ByteBuffer& b, Vector3& v)
34 b >> v.x >> v.y >> v.z;
37 enum MonsterMoveType
39 MonsterMoveNormal = 0,
40 MonsterMoveStop = 1,
41 MonsterMoveFacingSpot = 2,
42 MonsterMoveFacingTarget = 3,
43 MonsterMoveFacingAngle = 4
46 void PacketBuilder::WriteCommonMonsterMovePart(const MoveSpline& move_spline, WorldPacket& data)
48 MoveSplineFlag splineflags = move_spline.splineflags;
50 /*if (mov.IsBoarded())
52 data.SetOpcode(SMSG_MONSTER_MOVE_TRANSPORT);
53 data << mov.GetTransport()->Owner.GetPackGUID();
54 data << int8(mov.m_unused.transport_seat);
55 }*/
57 data << uint8(0);
58 data << move_spline.spline.getPoint(move_spline.spline.first());
59 data << move_spline.GetId();
61 switch (splineflags & MoveSplineFlag::Mask_Final_Facing)
63 default:
64 data << uint8(MonsterMoveNormal);
65 break;
66 case MoveSplineFlag::Final_Target:
67 data << uint8(MonsterMoveFacingTarget);
68 data << move_spline.facing.target;
69 break;
70 case MoveSplineFlag::Final_Angle:
71 data << uint8(MonsterMoveFacingAngle);
72 data << NormalizeOrientation(move_spline.facing.angle);
73 break;
74 case MoveSplineFlag::Final_Point:
75 data << uint8(MonsterMoveFacingSpot);
76 data << move_spline.facing.f.x << move_spline.facing.f.y << move_spline.facing.f.z;
77 break;
80 // add fake Enter_Cycle flag - needed for client-side cyclic movement (client will erase first spline vertex after first cycle done)
81 splineflags.enter_cycle = move_spline.isCyclic();
82 data << uint32(splineflags & ~MoveSplineFlag::Mask_No_Monster_Move);
84 if (splineflags.animation)
86 data << splineflags.getAnimationId();
87 data << move_spline.effect_start_time;
90 data << move_spline.Duration();
92 if (splineflags.parabolic)
94 data << move_spline.vertical_acceleration;
95 data << move_spline.effect_start_time;
99 void WriteLinearPath(const Spline<int32>& spline, ByteBuffer& data)
101 uint32 last_idx = spline.getPointCount() - 3;
102 const Vector3* real_path = &spline.getPoint(1);
104 data << last_idx;
105 data << real_path[last_idx]; // destination
106 if (last_idx > 1)
108 Vector3 middle = (real_path[0] + real_path[last_idx]) / 2.f;
109 Vector3 offset;
110 // first and last points already appended
111 for (uint32 i = 1; i < last_idx; ++i)
113 offset = middle - real_path[i];
114 data.appendPackXYZ(offset.x, offset.y, offset.z);
119 void WriteCatmullRomPath(const Spline<int32>& spline, ByteBuffer& data)
121 uint32 count = spline.getPointCount() - 3;
122 data << count;
123 data.append<Vector3>(&spline.getPoint(2), count);
126 void WriteCatmullRomCyclicPath(const Spline<int32>& spline, ByteBuffer& data)
128 uint32 count = spline.getPointCount() - 3;
129 data << uint32(count + 1);
130 data << spline.getPoint(1); // fake point, client will erase it from the spline after first cycle done
131 data.append<Vector3>(&spline.getPoint(1), count);
134 void PacketBuilder::WriteMonsterMove(const MoveSpline& move_spline, WorldPacket& data)
136 WriteCommonMonsterMovePart(move_spline, data);
138 const Spline<int32>& spline = move_spline.spline;
139 MoveSplineFlag splineflags = move_spline.splineflags;
140 if (splineflags & MoveSplineFlag::UncompressedPath)
142 if (splineflags.cyclic)
143 WriteCatmullRomCyclicPath(spline, data);
144 else
145 WriteCatmullRomPath(spline, data);
147 else
148 WriteLinearPath(spline, data);
151 void PacketBuilder::WriteCreateBits(const MoveSpline& move_spline, ByteBuffer& data)
153 if (!data.WriteBit(!move_spline.Finalized()))
154 return;
156 MoveSplineFlag splineFlags = move_spline.splineflags;
157 uint32 nodes = move_spline.getPath().size();
158 bool hasSplineStartTime = move_spline.splineflags & (MoveSplineFlag::Trajectory | MoveSplineFlag::Animation);
159 bool hasSplineVerticalAcceleration = (move_spline.splineflags & MoveSplineFlag::Trajectory) && move_spline.effect_start_time < move_spline.Duration();
161 data.WriteBits(uint8(move_spline.spline.mode()), 2);
162 data.WriteBit(hasSplineStartTime);
163 data.WriteBits(nodes, 22);
165 switch (move_spline.splineflags & MoveSplineFlag::Mask_Final_Facing)
167 case MoveSplineFlag::Final_Target:
169 data.WriteBits(2, 2);
171 data.WriteGuidMask<4, 3, 7, 2, 6, 1, 0, 5>(ObjectGuid(move_spline.facing.target));
172 break;
174 case MoveSplineFlag::Final_Angle:
175 data.WriteBits(0, 2);
176 break;
177 case MoveSplineFlag::Final_Point:
178 data.WriteBits(1, 2);
179 break;
180 default:
181 data.WriteBits(3, 2);
182 break;
185 data.WriteBit(hasSplineVerticalAcceleration);
186 data.WriteBits(move_spline.splineflags.raw(), 25);
189 void PacketBuilder::WriteCreateBytes(const MoveSpline& move_spline, ByteBuffer& data)
191 if (!move_spline.Finalized())
193 MoveSplineFlag splineFlags = move_spline.splineflags;
194 uint32 nodes = move_spline.getPath().size();
195 bool hasSplineStartTime = move_spline.splineflags & (MoveSplineFlag::Trajectory | MoveSplineFlag::Animation);
196 bool hasSplineVerticalAcceleration = (move_spline.splineflags & MoveSplineFlag::Trajectory) && move_spline.effect_start_time < move_spline.Duration();
198 if (hasSplineVerticalAcceleration)
199 data << float(move_spline.vertical_acceleration); // added in 3.1
201 data << int32(move_spline.timePassed());
203 if (move_spline.splineflags & MoveSplineFlag::Final_Angle)
204 data << float(NormalizeOrientation(move_spline.facing.angle));
205 else if (move_spline.splineflags & MoveSplineFlag::Final_Target)
206 data.WriteGuidBytes<5, 3, 7, 1, 6, 4, 2, 0>(ObjectGuid(move_spline.facing.target));
208 for (uint32 i = 0; i < nodes; ++i)
210 data << float(move_spline.getPath()[i].z);
211 data << float(move_spline.getPath()[i].x);
212 data << float(move_spline.getPath()[i].y);
215 if (move_spline.splineflags & MoveSplineFlag::Final_Point)
216 data << float(move_spline.facing.f.x) << float(move_spline.facing.f.z) << float(move_spline.facing.f.y);
218 data << float(1.f);
219 data << int32(move_spline.Duration());
220 if (hasSplineStartTime)
221 data << int32(move_spline.effect_start_time); // added in 3.1
223 data << float(1.f);
226 if (!move_spline.isCyclic())
228 Vector3 dest = move_spline.FinalDestination();
229 data << float(dest.z);
230 data << float(dest.x);
231 data << float(dest.y);
233 else
234 data << Vector3::zero();
236 data << uint32(move_spline.GetId());