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"
22 #include "WorldPacket.h"
23 #include "../Creature.h"
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
;
39 MonsterMoveNormal
= 0,
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);
58 data
<< move_spline
.spline
.getPoint(move_spline
.spline
.first());
59 data
<< move_spline
.GetId();
61 switch (splineflags
& MoveSplineFlag::Mask_Final_Facing
)
64 data
<< uint8(MonsterMoveNormal
);
66 case MoveSplineFlag::Final_Target
:
67 data
<< uint8(MonsterMoveFacingTarget
);
68 data
<< move_spline
.facing
.target
;
70 case MoveSplineFlag::Final_Angle
:
71 data
<< uint8(MonsterMoveFacingAngle
);
72 data
<< NormalizeOrientation(move_spline
.facing
.angle
);
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
;
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);
105 data
<< real_path
[last_idx
]; // destination
108 Vector3 middle
= (real_path
[0] + real_path
[last_idx
]) / 2.f
;
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;
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
);
145 WriteCatmullRomPath(spline
, data
);
148 WriteLinearPath(spline
, data
);
151 void PacketBuilder::WriteCreateBits(const MoveSpline
& move_spline
, ByteBuffer
& data
)
153 if (!data
.WriteBit(!move_spline
.Finalized()))
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
));
174 case MoveSplineFlag::Final_Angle
:
175 data
.WriteBits(0, 2);
177 case MoveSplineFlag::Final_Point
:
178 data
.WriteBits(1, 2);
181 data
.WriteBits(3, 2);
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
);
219 data
<< int32(move_spline
.Duration());
220 if (hasSplineStartTime
)
221 data
<< int32(move_spline
.effect_start_time
); // added in 3.1
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
);
234 data
<< Vector3::zero();
236 data
<< uint32(move_spline
.GetId());