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