1
2 #include "floattext.h"
3
4 #include "graphics/Renderer.h"
5 #include "nx.h"
6 #include "object.h"
7 using namespace NXE::Graphics;
8 #include "map.h"
9
10 FloatText *FloatText::first = NULL;
11 FloatText *FloatText::last = NULL;
12
13 /*
14 void c------------------------------() {}
15 */
16
FloatText(int sprite)17 FloatText::FloatText(int sprite)
18 {
19 prev = NULL;
20 next = first;
21
22 if (first)
23 first->prev = this;
24 else
25 last = this;
26
27 first = this;
28 this->sprite = sprite;
29
30 Reset();
31 ObjectDestroyed = false;
32 }
33
~FloatText()34 FloatText::~FloatText()
35 {
36 if (this->next)
37 this->next->prev = this->prev;
38 if (this->prev)
39 this->prev->next = this->next;
40
41 if (this == first)
42 first = first->next;
43 if (this == last)
44 last = last->prev;
45 }
46
Reset()47 void FloatText::Reset()
48 {
49 this->state = FT_IDLE;
50 this->shownAmount = 0;
51 }
52
53 /*
54 void c------------------------------() {}
55 */
56
57 // adds the spec'd amount of damage/energy to the object's point display
AddQty(int amt)58 void FloatText::AddQty(int amt)
59 {
60 // stat("FloatText::AddQty(%d)", amt);
61 if (amt == 0)
62 return;
63
64 // first add the damage to the total
65 if (this->state == FT_IDLE)
66 {
67 this->state = FT_RISE;
68
69 this->shownAmount = amt;
70 this->yoff = FT_Y_START;
71 this->timer = 0;
72 }
73 else
74 {
75 this->shownAmount += amt;
76
77 // if we're scrolling away jerk back down
78 if (this->state == FT_SCROLL_AWAY)
79 {
80 this->state = FT_HOLD;
81 this->yoff = FT_Y_HOLD;
82 }
83
84 // reset the timer which counts how long we stay in hold state
85 if (this->state != FT_RISE)
86 this->timer = 0;
87 }
88
89 if (this->shownAmount > 9999)
90 this->shownAmount = 9999; // overrun protection for buffer
91 }
92
93 // updates the position of a floattext in respect to it's object
UpdatePos(Object * assoc_object)94 void FloatText::UpdatePos(Object *assoc_object)
95 {
96 // get the center pixel of the object we're associated with
97 this->objX = (assoc_object->x / CSFI) + (Renderer::getInstance()->sprites.sprites[assoc_object->sprite].w / 2);
98 this->objY = (assoc_object->y / CSFI) + (Renderer::getInstance()->sprites.sprites[assoc_object->sprite].h / 2);
99
100 // adjust for possible draw point
101 SIFDir *dir = &Renderer::getInstance()->sprites.sprites[assoc_object->sprite].frame[assoc_object->frame].dir[assoc_object->dir];
102 this->objX -= dir->drawpoint.x;
103 this->objY -= dir->drawpoint.y;
104 }
105
106 // moves and draws the given float text if need be
Draw()107 void FloatText::Draw()
108 {
109 FloatText *ft = this;
110 int x, y, i;
111
112 // set the SDL clipping region to just above the hold point
113 // so it looks like it "rolls" away.
114 if (ft->state == FT_SCROLL_AWAY)
115 {
116 // this formula is confusing until you realize that FT_Y_HOLD is a negative number
117 int y = ((ft->objY - (map.displayed_yscroll / CSFI)) + FT_Y_HOLD);
118 int h = (Renderer::getInstance()->screenHeight - y);
119
120 Renderer::getInstance()->setClip(0, y, Renderer::getInstance()->screenWidth, h);
121 }
122
123 // render the damage amount into a string
124 char text[6] = {10};
125 sprintf(&text[1], "%d", ft->shownAmount);
126 for (i = 1; text[i]; i++)
127 text[i] -= '0';
128 int textlen = i;
129
130 x = ft->objX - (textlen * (8 / 2)); // center the string on the object
131 y = ft->objY + ft->yoff;
132 // adjust to object's onscreen position
133 x -= (map.displayed_xscroll / CSFI);
134 y -= (map.displayed_yscroll / CSFI);
135
136 // draw the text char by char
137 for (i = 0; i < textlen; i++)
138 {
139 Renderer::getInstance()->sprites.drawSprite(x, y, ft->sprite, text[i], 0);
140 x += 8;
141 }
142
143 if (ft->state == FT_SCROLL_AWAY)
144 Renderer::getInstance()->clearClip();
145 }
146
Update()147 void FloatText::Update()
148 {
149 FloatText *ft = this;
150
151 switch (ft->state)
152 {
153 // rise to top point, moving once every other frame
154 case FT_RISE:
155 {
156 ft->timer ^= 1;
157 if (ft->timer)
158 {
159 if (--ft->yoff <= FT_Y_HOLD)
160 {
161 ft->state = FT_HOLD;
162 ft->timer = 0;
163 }
164 }
165 }
166 break;
167
168 // hold at top for a moment
169 case FT_HOLD:
170 {
171 if (++ft->timer >= 42)
172 ft->state = FT_SCROLL_AWAY;
173 }
174 break;
175
176 // scroll away quickly and disappear
177 case FT_SCROLL_AWAY:
178 {
179 if (--ft->yoff <= FT_Y_RISEAWAY)
180 {
181 ft->state = FT_IDLE;
182 ft->shownAmount = 0;
183 ft->timer = 0;
184 return;
185 }
186 }
187 break;
188 }
189 }
190
IsScrollingAway()191 bool FloatText::IsScrollingAway()
192 {
193 return (this->state == FT_SCROLL_AWAY);
194 }
195
196 /*
197 void c------------------------------() {}
198 */
199
DrawAll(void)200 void FloatText::DrawAll(void)
201 {
202 FloatText *ft = first;
203 FloatText *nextft;
204 int count = 0;
205
206 while (ft)
207 {
208 nextft = ft->next;
209
210 if (ft->state != FT_IDLE)
211 {
212 ft->Draw();
213 }
214 else
215 {
216 if (ft->ObjectDestroyed)
217 delete ft;
218 }
219
220 ft = nextft;
221 count++;
222 }
223 }
224
UpdateAll(void)225 void FloatText::UpdateAll(void)
226 {
227 FloatText *ft = first;
228 FloatText *nextft;
229 int count = 0;
230
231 while (ft)
232 {
233 nextft = ft->next;
234
235 if (ft->state != FT_IDLE)
236 {
237 ft->Update();
238 }
239 else
240 {
241 if (ft->ObjectDestroyed)
242 delete ft;
243 }
244
245 ft = nextft;
246 count++;
247 }
248 }
249
250 // do NOT call this to remove all enemy's floattext from the map.
251 // for one thing, it could leave dangling invalid pointers.
252 // for another, it deletes the player->XPText, etc.
253 // instead, call ResetAll and let them clean themselves up.
DeleteAll(void)254 void FloatText::DeleteAll(void)
255 {
256 while (first)
257 delete first;
258 }
259
ResetAll(void)260 void FloatText::ResetAll(void)
261 {
262 FloatText *ft = first;
263 while (ft)
264 {
265 ft->Reset();
266 ft = ft->next;
267 }
268 }
269