]> git.localhorst.tv Git - l2e.git/blob - src/map/Entity.cpp
b9261a2ae8df1aa2dc985876de00baed3d483491
[l2e.git] / src / map / Entity.cpp
1 /*
2  * Entity.cpp
3  *
4  *  Created on: Sep 29, 2012
5  *      Author: holy
6  */
7
8 #include "Entity.h"
9
10 #include "../battle/Monster.h"
11 #include "../battle/PartyLayout.h"
12 #include "../graphics/Animation.h"
13 #include "../graphics/Sprite.h"
14 #include "../loader/Interpreter.h"
15 #include "../loader/TypeDescription.h"
16
17 using battle::Monster;
18 using battle::PartyLayout;
19 using graphics::Animation;
20 using graphics::Sprite;
21 using geometry::Vector;
22 using loader::FieldDescription;
23 using loader::Interpreter;
24 using loader::TypeDescription;
25
26 namespace map {
27
28 Entity::Entity()
29 : follower(0)
30 , animation(0)
31 , sprite(0)
32 , partyLayout(0)
33 , monsters(0)
34 , numMonsters(0)
35 , orientation(ORIENTATION_NORTH)
36 , speed(0)
37 , flags(0) {
38         runner.SetFrameShift(1);
39 }
40
41
42 void Entity::SetOrientation(Orientation o) {
43         orientation = o;
44         UpdateVelocity();
45         if (CanTurn()) {
46                 runner.SetColOffset(orientation);
47         }
48 }
49
50 void Entity::SetSpeed(float s) {
51         speed = s;
52         UpdateVelocity();
53 }
54
55
56 void Entity::StartAnimation(app::Application &ctrl) {
57         runner.Start(ctrl);
58 }
59
60 void Entity::StartAnimation(app::State &ctrl) {
61         runner.Start(ctrl);
62 }
63
64 void Entity::StopAnimation() {
65         runner.Stop();
66 }
67
68
69 void Entity::SetHandsFree() {
70         runner.SetRowOffset(0);
71 }
72
73 void Entity::SetCarrying() {
74         runner.SetRowOffset(2);
75 }
76
77 void Entity::SetPushing() {
78         runner.SetRowOffset(4);
79 }
80
81
82 void Entity::AddFollower(Entity *f) {
83         if (follower) {
84                 follower->AddFollower(f);
85         } else {
86                 follower = f;
87         }
88 }
89
90 void Entity::RemoveFollower(Entity *f) {
91         if (follower == f) {
92                 follower = follower->follower;
93         } else if (follower) {
94                 follower->RemoveFollower(f);
95         }
96 }
97
98 void Entity::SetAnimation(const graphics::Animation *a) {
99         animation = a;
100         runner.ChangeAnimation(animation);
101         if (!sprite) {
102                 sprite = animation->GetSprite();
103         }
104 }
105
106
107 void Entity::UpdateVelocity() {
108         if (speed == 0.0f) {
109                 velocity = Vector<float>();
110                 return;
111         }
112         switch (orientation) {
113                 case ORIENTATION_NORTH:
114                         velocity = Vector<float>(0.0f, -speed);
115                         break;
116                 case ORIENTATION_EAST:
117                         velocity = Vector<float>(speed, 0.0f);
118                         break;
119                 case ORIENTATION_SOUTH:
120                         velocity = Vector<float>(0.0f, speed);
121                         break;
122                 case ORIENTATION_WEST:
123                         velocity = Vector<float>(-speed, 0.0f);
124                         break;
125         }
126 }
127
128
129 bool Entity::TileLock(const geometry::Vector<int> &tileSize) const {
130         // TODO: change position to point to the top-left corner of a tile
131         Vector<int> tilePosition(position);
132         return (tilePosition.X() % tileSize.X() == 0) && (tilePosition.Y() % tileSize.Y() == 0);
133 }
134
135
136 void Entity::Update(float deltaT) {
137         position += velocity * deltaT;
138 }
139
140
141 void Entity::Render(SDL_Surface *dest, const Vector<int> &offset) const {
142         // TODO: configurable sprite offsets
143         if (runner.Running()) {
144                 runner.Draw(dest, offset + position + spriteOffset);
145         } else {
146                 sprite->Draw(dest, offset + position + spriteOffset, CanTurn() ? orientation : 0);
147         }
148 }
149
150
151 void Entity::CreateTypeDescription() {
152         Entity e;
153
154         TypeDescription &td(TypeDescription::Create(TYPE_ID, "Entity"));
155         td.SetConstructor(&Construct);
156         td.SetLoader(&Load);
157         td.SetSize(sizeof(Entity));
158
159         td.AddField("animation", FieldDescription(((char *)&e.animation) - ((char *)&e), Animation::TYPE_ID).SetReferenced());
160         td.AddField("sprite", FieldDescription(((char *)&e.sprite) - ((char *)&e), Sprite::TYPE_ID).SetReferenced());
161         td.AddField("partyLayout", FieldDescription(((char *)&e.partyLayout) - ((char *)&e), PartyLayout::TYPE_ID).SetReferenced());
162         td.AddField("monsters", FieldDescription(((char *)&e.monsters) - ((char *)&e), Monster::TYPE_ID).SetReferenced().SetAggregate());
163         td.AddField("spriteOffset", FieldDescription(((char *)&e.spriteOffset) - ((char *)&e), Interpreter::VECTOR_ID));
164         td.AddField("position", FieldDescription(((char *)&e.tilePosition) - ((char *)&e), Interpreter::VECTOR_ID));
165         td.AddField("flags", FieldDescription(((char *)&e.flags) - ((char *)&e), Interpreter::NUMBER_ID));
166 }
167
168 void Entity::Construct(void *data) {
169         new (data) Entity;
170 }
171
172 void Entity::Load(void *data) {
173         Entity *entity(reinterpret_cast<Entity *>(data));
174         if (entity->animation) {
175                 entity->runner.ChangeAnimation(entity->animation);
176                 if (!entity->sprite) {
177                         entity->sprite = entity->animation->GetSprite();
178                 }
179         }
180 }
181
182 }