~ubuntu-branches/ubuntu/precise/widelands/precise-backports

« back to all changes in this revision

Viewing changes to src/soldier.cc

  • Committer: Bazaar Package Importer
  • Author(s): Martin Quinson
  • Date: 2005-02-14 10:41:12 UTC
  • Revision ID: james.westby@ubuntu.com-20050214104112-6v08iux9fptxpva9
Tags: upstream-build9
Import upstream version build9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2002-4 by the Widelands Development Team
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU General Public License
 
6
 * as published by the Free Software Foundation; either version 2
 
7
 * of the License, or (at your option) any later version.
 
8
 *
 
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.
 
13
 *
 
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., 675 Mass Ave, Cambridge, MA 02139, USA.
 
17
 *
 
18
 */
 
19
 
 
20
#include <stdio.h>
 
21
#include "battle.h"
 
22
#include "editor_game_base.h"
 
23
#include "error.h"
 
24
#include "game.h"
 
25
#include "graphic.h"
 
26
#include "militarysite.h"
 
27
#include "player.h"
 
28
#include "profile.h"
 
29
#include "rendertarget.h"
 
30
#include "rgbcolor.h"
 
31
#include "soldier.h"
 
32
#include "transport.h"
 
33
#include "tribe.h"
 
34
#include "util.h"
 
35
#include "warehouse.h"
 
36
#include "wexception.h"
 
37
 
 
38
 
 
39
/*
 
40
==============================================================================
 
41
 
 
42
IdleSoldierSupply IMPLEMENTATION
 
43
 
 
44
==============================================================================
 
45
*/
 
46
 
 
47
class IdleSoldierSupply : public Supply {
 
48
        public:
 
49
                IdleSoldierSupply(Soldier* w);
 
50
                ~IdleSoldierSupply();
 
51
 
 
52
                void set_economy(Economy* e);
 
53
 
 
54
        public:
 
55
                virtual PlayerImmovable* get_position(Game* g);
 
56
                virtual int get_amount(Game* g, int ware);
 
57
                virtual bool is_active(Game* g);
 
58
 
 
59
                virtual WareInstance* launch_item(Game* g, int ware);
 
60
                virtual Worker* launch_worker(Game* g, int ware);
 
61
 
 
62
                virtual Soldier* launch_soldier(Game* g, int ware, Requeriments* req);
 
63
                virtual int get_passing_requeriments(Game* g, int ware, Requeriments* r);
 
64
                virtual void mark_as_used (Game* g, int ware, Requeriments* r);
 
65
        private:
 
66
                Soldier*                m_soldier;
 
67
                Economy*                m_economy;
 
68
};
 
69
 
 
70
 
 
71
/*
 
72
===============
 
73
IdleSoldierSupply::IdleSoldierSupply
 
74
 
 
75
Automatically register with the soldier's economy.
 
76
===============
 
77
*/
 
78
IdleSoldierSupply::IdleSoldierSupply(Soldier* s)
 
79
{
 
80
        m_soldier = s;
 
81
        m_economy = 0;
 
82
 
 
83
        set_economy(s->get_economy());
 
84
}
 
85
 
 
86
 
 
87
/*
 
88
===============
 
89
IdleSoldierSupply::~IdleSoldierSupply
 
90
 
 
91
Automatically unregister from economy.
 
92
===============
 
93
*/
 
94
IdleSoldierSupply::~IdleSoldierSupply()
 
95
{
 
96
        set_economy(0);
 
97
}
 
98
 
 
99
 
 
100
/*
 
101
===============
 
102
IdleSoldierSupply::set_economy
 
103
 
 
104
Add/remove this supply from the Economy as appropriate.
 
105
===============
 
106
*/
 
107
void IdleSoldierSupply::set_economy(Economy* e)
 
108
{
 
109
        if (m_economy == e)
 
110
                return;
 
111
 
 
112
        if (m_economy)
 
113
                m_economy->remove_soldier_supply(m_soldier->get_owner()->get_tribe()->get_worker_index(m_soldier->get_name().c_str()), this);
 
114
 
 
115
        m_economy = e;
 
116
 
 
117
        if (m_economy)
 
118
                m_economy->add_soldier_supply(m_soldier->get_owner()->get_tribe()->get_worker_index(m_soldier->get_name().c_str()), this);
 
119
}
 
120
 
 
121
 
 
122
/*
 
123
===============
 
124
IdleSoldierSupply::get_position
 
125
 
 
126
Return the soldier's position.
 
127
===============
 
128
*/
 
129
PlayerImmovable* IdleSoldierSupply::get_position(Game* g)
 
130
{
 
131
        return m_soldier->get_location(g);
 
132
}
 
133
 
 
134
 
 
135
/*
 
136
===============
 
137
IdleSoldierSupply::get_amount
 
138
 
 
139
It's just the one soldier.
 
140
===============
 
141
*/
 
142
int IdleSoldierSupply::get_amount(Game* g, int ware)
 
143
{
 
144
        if (ware == m_soldier->get_owner()->get_tribe()->get_worker_index(m_soldier->get_name().c_str()))
 
145
                return 1;
 
146
 
 
147
        return 0;
 
148
}
 
149
 
 
150
 
 
151
/*
 
152
===============
 
153
IdleSoldierSupply::is_active
 
154
 
 
155
Idle soldiers are always active supplies, because they need to get into a
 
156
Warehouse ASAP.
 
157
===============
 
158
*/
 
159
bool IdleSoldierSupply::is_active(Game* g)
 
160
{
 
161
        return true;
 
162
}
 
163
 
 
164
 
 
165
/*
 
166
===============
 
167
IdleSoldierSupply::launch_item
 
168
===============
 
169
*/
 
170
WareInstance* IdleSoldierSupply::launch_item(Game* g, int ware)
 
171
{
 
172
        throw wexception("IdleSoldierSupply::launch_item() makes no sense.");
 
173
}
 
174
 
 
175
 
 
176
/*
 
177
===============
 
178
IdleSodlierSupply::launch_worker
 
179
===============
 
180
*/
 
181
Worker* IdleSoldierSupply::launch_worker(Game* g, int ware)
 
182
{
 
183
        log ("IdleSoldierSupply::launch_worker() Warning something can go wrong around here.\n");
 
184
 
 
185
        return launch_soldier(g, ware, NULL);
 
186
}
 
187
 
 
188
 
 
189
/*
 
190
===============
 
191
IdleSodlierSupply::launch_soldier
 
192
 
 
193
No need to explicitly launch the soldier.
 
194
===============
 
195
*/
 
196
Soldier* IdleSoldierSupply::launch_soldier(Game* g, int ware, Requeriments* req)
 
197
{
 
198
        assert(ware == m_soldier->get_owner()->get_tribe()->get_worker_index(m_soldier->get_name().c_str()));
 
199
 
 
200
        if (req)
 
201
        {
 
202
                if (req->check (
 
203
                                  m_soldier->get_level(atrHP),
 
204
                m_soldier->get_level(atrAttack),
 
205
                m_soldier->get_level(atrDefense),
 
206
                m_soldier->get_level(atrEvade)
 
207
                                                        ))
 
208
                {
 
209
                        // Ensures that this soldier is used now
 
210
                        m_soldier->mark (false);
 
211
                        return m_soldier;
 
212
                }
 
213
                else
 
214
                        throw wexception ("IdleSoldierSupply::launch_soldier Fails. Requeriments aren't accomplished.");
 
215
        }
 
216
        else
 
217
                return m_soldier;
 
218
}
 
219
 
 
220
/*
 
221
===============
 
222
IdleSodlierSupply::mark_as_used
 
223
===============
 
224
*/
 
225
void IdleSoldierSupply::mark_as_used(Game* g, int ware, Requeriments* req)
 
226
{
 
227
        assert(ware == m_soldier->get_owner()->get_tribe()->get_worker_index(m_soldier->get_name().c_str()));
 
228
 
 
229
        if (req)
 
230
        {
 
231
                if (req->check (
 
232
                                  m_soldier->get_level(atrHP),
 
233
                m_soldier->get_level(atrAttack),
 
234
                m_soldier->get_level(atrDefense),
 
235
                m_soldier->get_level(atrEvade)
 
236
                                                        ))
 
237
                {
 
238
                        // Ensures that this soldier has a request now
 
239
                        m_soldier->mark (true);
 
240
                }
 
241
                else
 
242
                        throw wexception ("IdleSoldierSupply::launch_soldier Fails. Requeriments aren't accomplished.");
 
243
        }
 
244
        else
 
245
                m_soldier->mark (true);
 
246
}
 
247
 
 
248
 
 
249
/*
 
250
===============
 
251
IdleSodlierSupply::get_passing_requeriments
 
252
 
 
253
No need to explicitly launch the soldier.
 
254
===============
 
255
*/
 
256
int IdleSoldierSupply::get_passing_requeriments(Game* g, int ware, Requeriments* req)
 
257
{
 
258
        assert(ware == m_soldier->get_owner()->get_tribe()->get_worker_index(m_soldier->get_name().c_str()));
 
259
 
 
260
        // Oops we find a marked soldied (in use)
 
261
        if (m_soldier->is_marked())
 
262
                return 0;
 
263
 
 
264
        if (!req)
 
265
                return 1;
 
266
 
 
267
        if (req->check (
 
268
                        m_soldier->get_level(atrHP),
 
269
        m_soldier->get_level(atrAttack),
 
270
        m_soldier->get_level(atrDefense),
 
271
        m_soldier->get_level(atrEvade)
 
272
                                                ))
 
273
                return 1;
 
274
        else
 
275
                return 0;
 
276
}
 
277
 
 
278
 
 
279
 
 
280
 
 
281
/*
 
282
==============================================================
 
283
 
 
284
SOLDIER DESCRIPTION IMPLEMENTATION
 
285
 
 
286
==============================================================
 
287
*/
 
288
 
 
289
/*
 
290
===============
 
291
Soldier_Descr::Soldier_Descr
 
292
Soldier_Descr::~Soldier_Descr
 
293
===============
 
294
*/
 
295
Soldier_Descr::Soldier_Descr(Tribe_Descr *tribe, const char *name)
 
296
        : Worker_Descr(tribe, name)
 
297
{
 
298
        add_attribute(Map_Object::SOLDIER);
 
299
}
 
300
 
 
301
Soldier_Descr::~Soldier_Descr(void)
 
302
{
 
303
   m_hp_pics_fn.resize(0);
 
304
   m_attack_pics_fn.resize(0);
 
305
   m_defense_pics_fn.resize(0);
 
306
   m_evade_pics_fn.resize(0);
 
307
}
 
308
 
 
309
/**
 
310
===============
 
311
Soldier_Descr::parse
 
312
 
 
313
Parse carrier-specific configuration data
 
314
===============
 
315
*/
 
316
void Soldier_Descr::parse(const char *directory, Profile *prof, const EncodeData *encdata)
 
317
{
 
318
        Worker_Descr::parse(directory, prof, encdata);
 
319
   Section* sglobal=prof->get_section("global");
 
320
  
 
321
   // Parse hitpoints
 
322
   std::string hp=sglobal->get_safe_string("hp");
 
323
   std::vector<std::string> list;
 
324
   split_string(hp, &list, "-");
 
325
   if(list.size()!=2) 
 
326
      throw wexception("Parse error in hp string: \"%s\" (must be \"min-max\")", hp.c_str());
 
327
   uint i=0;
 
328
   for(i=0; i<list.size(); i++)
 
329
      remove_spaces(&list[i]);
 
330
   char* endp;
 
331
   m_min_hp= strtol(list[0].c_str(),&endp, 0);
 
332
   if(endp && *endp)
 
333
      throw wexception("Parse error in hp string: %s is a bad value", list[0].c_str());
 
334
   m_max_hp = strtol(list[1].c_str(),&endp, 0);
 
335
   if(endp && *endp)
 
336
      throw wexception("Parse error in hp string: %s is a bad value", list[1].c_str());
 
337
 
 
338
   // Parse attack
 
339
   std::string attack=sglobal->get_safe_string("attack");
 
340
   list.resize(0);
 
341
   split_string(attack, &list, "-");
 
342
   if(list.size()!=2) 
 
343
      throw wexception("Parse error in attack string: \"%s\" (must be \"min-max\")", attack.c_str());
 
344
   for(i=0; i<list.size(); i++)
 
345
      remove_spaces(&list[i]);
 
346
   m_min_attack= strtol(list[0].c_str(),&endp, 0);
 
347
   if(endp && *endp)
 
348
      throw wexception("Parse error in attack string: %s is a bad value", list[0].c_str());
 
349
   m_max_attack = strtol(list[1].c_str(),&endp, 0);
 
350
   if(endp && *endp)
 
351
      throw wexception("Parse error in attack string: %s is a bad value", list[1].c_str());
 
352
 
 
353
   // Parse defend
 
354
   m_defense=sglobal->get_safe_int("defense");
 
355
   
 
356
   // Parse evade
 
357
   m_evade=sglobal->get_safe_int("evade");
 
358
 
 
359
   // Parse increases per level
 
360
   m_hp_incr=sglobal->get_safe_int("hp_incr_per_level");
 
361
   m_attack_incr=sglobal->get_safe_int("attack_incr_per_level");
 
362
   m_defense_incr=sglobal->get_safe_int("defense_incr_per_level");
 
363
   m_evade_incr=sglobal->get_safe_int("evade_incr_per_level");
 
364
 
 
365
   // Parse max levels
 
366
   m_max_hp_level=sglobal->get_safe_int("max_hp_level");
 
367
   m_max_attack_level=sglobal->get_safe_int("max_attack_level");
 
368
   m_max_defense_level=sglobal->get_safe_int("max_defense_level");
 
369
   m_max_evade_level=sglobal->get_safe_int("max_evade_level");
 
370
 
 
371
   // Load the filenames
 
372
   m_hp_pics_fn.resize(m_max_hp_level+1);
 
373
   m_attack_pics_fn.resize(m_max_attack_level+1);
 
374
   m_defense_pics_fn.resize(m_max_defense_level+1);
 
375
   m_evade_pics_fn.resize(m_max_evade_level+1);
 
376
   char buffer[256];
 
377
   std::string dir=directory;
 
378
   dir+="/";
 
379
   for(i=0; i<=m_max_hp_level; i++) {
 
380
      sprintf(buffer, "hp_level_%i_pic", i);
 
381
      m_hp_pics_fn[i]=dir;
 
382
      m_hp_pics_fn[i]+=sglobal->get_safe_string(buffer);
 
383
   }
 
384
   for(i=0; i<=m_max_attack_level; i++) {
 
385
      sprintf(buffer, "attack_level_%i_pic", i);
 
386
      m_attack_pics_fn[i]=dir;
 
387
      m_attack_pics_fn[i]+=sglobal->get_safe_string(buffer);
 
388
   }
 
389
   for(i=0; i<=m_max_defense_level; i++) {
 
390
      sprintf(buffer, "defense_level_%i_pic", i);
 
391
      m_defense_pics_fn[i]=dir;
 
392
      m_defense_pics_fn[i]+=sglobal->get_safe_string(buffer);
 
393
   }
 
394
   for(i=0; i<=m_max_evade_level; i++) {
 
395
      sprintf(buffer, "evade_level_%i_pic", i);
 
396
      m_evade_pics_fn[i]=dir;
 
397
      m_evade_pics_fn[i]+=sglobal->get_safe_string(buffer);
 
398
   }
 
399
}
 
400
 
 
401
/**
 
402
 * Load the graphics
 
403
 */
 
404
void Soldier_Descr::load_graphics(void) {
 
405
   m_hp_pics.resize(m_max_hp_level+1);
 
406
   m_attack_pics.resize(m_max_attack_level+1);
 
407
   m_defense_pics.resize(m_max_defense_level+1);
 
408
   m_evade_pics.resize(m_max_evade_level+1);
 
409
   uint i;
 
410
   for(i=0; i<=m_max_hp_level; i++) {
 
411
      m_hp_pics[i]=g_gr->get_picture(PicMod_Game, m_hp_pics_fn[i].c_str(), true);
 
412
   }
 
413
   for(i=0; i<=m_max_attack_level; i++) {
 
414
      m_attack_pics[i]=g_gr->get_picture(PicMod_Game, m_attack_pics_fn[i].c_str(), true);
 
415
   }
 
416
   for(i=0; i<=m_max_defense_level; i++) {
 
417
      m_defense_pics[i]=g_gr->get_picture(PicMod_Game, m_defense_pics_fn[i].c_str(), true);
 
418
   }
 
419
   for(i=0; i<=m_max_evade_level; i++) {
 
420
      m_evade_pics[i]=g_gr->get_picture(PicMod_Game, m_evade_pics_fn[i].c_str(), true);
 
421
   }
 
422
   Worker_Descr::load_graphics();
 
423
}
 
424
 
 
425
 
 
426
/**
 
427
 * Get random animation of specified type
 
428
 */
 
429
uint Soldier_Descr::get_rand_anim(std::string name)
 
430
{
 
431
   // Todo: This is thought to get a random animation like attack_1 attack_2 attack_3 ...
 
432
   // Randimly trhought this method. By now only gets attack, but isn't very difficult 
 
433
   // to remake allowing the attack_1 and so.
 
434
   return get_animation(name.c_str());
 
435
}
 
436
 
 
437
/**
 
438
 * Create a new soldier
 
439
 */
 
440
Bob* Soldier_Descr::create_object() {
 
441
   return new Soldier(this);
 
442
}
 
443
 
 
444
/*
 
445
==============================
 
446
 
 
447
IMPLEMENTATION
 
448
 
 
449
==============================
 
450
*/
 
451
 
 
452
/*
 
453
===============
 
454
Soldier::Soldier
 
455
Soldier::~Soldier
 
456
===============
 
457
*/
 
458
Soldier::Soldier(Soldier_Descr *descr)
 
459
        : Worker(descr)
 
460
{
 
461
   // all done through init
 
462
}
 
463
 
 
464
Soldier::~Soldier()
 
465
{
 
466
}
 
467
 
 
468
/*
 
469
 * Initialize this soldier
 
470
 */
 
471
void Soldier::init(Editor_Game_Base* gg) {
 
472
        m_hp_level=0;
 
473
        m_attack_level=0;
 
474
        m_defense_level=0;
 
475
        m_evade_level=0;
 
476
 
 
477
        m_hp_max=0;
 
478
        m_min_attack=get_descr()->get_min_attack();
 
479
        m_max_attack=get_descr()->get_max_attack();
 
480
        m_defense=get_descr()->get_defense();
 
481
        m_evade=get_descr()->get_evade();
 
482
        if(gg->is_game()) {
 
483
                Game* g= static_cast<Game*>(gg);
 
484
                int range=get_descr()->get_max_hp()-get_descr()->get_min_hp();
 
485
                int value=g->logic_rand() % range;
 
486
                m_hp_max=value;
 
487
        }
 
488
        m_hp_current=m_hp_max;
 
489
 
 
490
        m_marked = false;
 
491
 
 
492
        Worker::init(gg);
 
493
}
 
494
 
 
495
/*
 
496
 * Set this soldiers level. Automatically sets the new values
 
497
 */
 
498
void Soldier::set_level(uint hp, uint attack, uint defense, uint evade) {
 
499
   set_hp_level(hp);
 
500
   set_attack_level(attack);
 
501
   set_defense_level(defense);
 
502
   set_evade_level(evade);
 
503
}
 
504
void Soldier::set_hp_level(uint hp) {
 
505
   assert(hp>=m_hp_level && hp<=get_descr()->get_max_hp_level());
 
506
   
 
507
   while(m_hp_level<hp) {
 
508
      ++m_hp_level;
 
509
      m_hp_max+=get_descr()->get_hp_incr_per_level();
 
510
      m_hp_current+=get_descr()->get_hp_incr_per_level();
 
511
   }
 
512
}
 
513
void Soldier::set_attack_level(uint attack) {
 
514
   assert(attack>=m_attack_level && attack<=get_descr()->get_max_attack_level());
 
515
   
 
516
   while(m_attack_level<attack) {
 
517
      ++m_attack_level;
 
518
      m_min_attack+=get_descr()->get_attack_incr_per_level();
 
519
      m_max_attack+=get_descr()->get_attack_incr_per_level();
 
520
   }
 
521
}
 
522
void Soldier::set_defense_level(uint defense) {
 
523
   assert(defense>=m_defense_level && defense<=get_descr()->get_max_defense_level());
 
524
   
 
525
   while(m_defense_level<defense) {
 
526
      ++m_defense_level;
 
527
      m_defense+=get_descr()->get_defense_incr_per_level();
 
528
   }
 
529
}
 
530
void Soldier::set_evade_level(uint evade) {
 
531
   assert(evade>=m_evade_level && evade<=get_descr()->get_max_evade_level());
 
532
   
 
533
   while(m_evade_level<evade) {
 
534
      ++m_evade_level;
 
535
      m_evade+=get_descr()->get_evade_incr_per_level();
 
536
   }
 
537
}
 
538
 
 
539
uint Soldier::get_level(tAttribute at)
 
540
{
 
541
        switch (at)
 
542
        {
 
543
                case atrHP:        return m_hp_level;
 
544
                case atrAttack:    return m_attack_level;
 
545
                case atrDefense:   return m_defense_level;
 
546
                case atrEvade:     return m_evade_level;
 
547
      case atrTotal: return m_hp_level + m_attack_level + m_defense_level + m_evade_level;
 
548
        }
 
549
        throw wexception ("Soldier::get_level attribute not identified.)");
 
550
}
 
551
 
 
552
void Soldier::heal (uint hp)
 
553
{
 
554
        // Ensures that we can only heal, don't hurt throught this method
 
555
        assert (hp >= 0);
 
556
 
 
557
   molog ("healing (%d+)%d/%d\n", hp, m_hp_current, m_hp_max);
 
558
        m_hp_current += hp;
 
559
 
 
560
        if (m_hp_current > m_hp_max)
 
561
                m_hp_current = m_hp_max;
 
562
}
 
563
 
 
564
/**
 
565
 * This only subs the specified number of hitpoints, don't do anything more.
 
566
 */
 
567
void Soldier::damage (uint value)
 
568
{
 
569
   assert (m_hp_current > 0);
 
570
   
 
571
   molog ("damage %d(-%d)/%d\n", m_hp_current, value, m_hp_max);
 
572
   if (m_hp_current < value)
 
573
      m_hp_current = 0;
 
574
   else
 
575
      m_hp_current -= value;
 
576
}
 
577
 
 
578
/*
 
579
 * Draw this soldier. This basically draws him as a worker, but add hitpoints
 
580
 */
 
581
void Soldier::draw(Editor_Game_Base* g, RenderTarget* dst, Point pos) {
 
582
   uint anim = get_current_anim();
 
583
 
 
584
        if (!anim)
 
585
                return;
 
586
 
 
587
        Point drawpos;
 
588
        calc_drawpos(g, pos, &drawpos);
 
589
 
 
590
   int w, h;
 
591
   g_gr->get_animation_size(anim, g->get_gametime() - get_animstart(), &w, &h);
 
592
   
 
593
   // Draw energy bar
 
594
   // first: draw white sourrounding
 
595
   const int frame_width=w<<1;  // width * 2
 
596
   const int frame_height=5;
 
597
   const int frame_beginning_x=drawpos.x-(frame_width>>1);  // TODO: these should be calculated from the hot spot, not assumed
 
598
   const int frame_beginning_y=drawpos.y-h-7;     
 
599
   dst->draw_rect(frame_beginning_x, frame_beginning_y, frame_width, frame_height, HP_FRAMECOLOR);
 
600
   // Draw energybar
 
601
   float percent = (float)m_hp_current/m_hp_max;
 
602
   int energy_width=static_cast<int>(percent * (frame_width-2));
 
603
   RGBColor color;
 
604
   if (percent <= 0.15)
 
605
                color = RGBColor(255, 0, 0);
 
606
        else if (percent <= 0.5)
 
607
                color = RGBColor(255, 255, 0);
 
608
        else
 
609
                color = RGBColor(17,192,17);
 
610
   dst->fill_rect(frame_beginning_x+1, frame_beginning_y+1, energy_width, frame_height-2, color); 
 
611
 
 
612
   // Draw information fields about levels
 
613
   // first, gather informations
 
614
   uint hppic=get_hp_level_pic();
 
615
   uint attackpic=get_attack_level_pic();
 
616
   uint defensepic=get_defense_level_pic();
 
617
   uint evadepic=get_evade_level_pic();
 
618
   int hpw,hph,atw,ath,dew,deh,evw,evh; 
 
619
   g_gr->get_picture_size(hppic, &hpw, &hph);
 
620
   g_gr->get_picture_size(attackpic, &atw, &ath);
 
621
   g_gr->get_picture_size(defensepic, &dew, &deh);
 
622
   g_gr->get_picture_size(evadepic, &evw, &evh);
 
623
 
 
624
   dst->blit(frame_beginning_x, frame_beginning_y-hph-ath, attackpic);
 
625
   dst->blit(frame_beginning_x+(frame_width>>1), frame_beginning_y-evh-deh, defensepic);
 
626
   dst->blit(frame_beginning_x, frame_beginning_y-hph, hppic);
 
627
   dst->blit(frame_beginning_x+(frame_width>>1), frame_beginning_y-evh, evadepic);
 
628
   
 
629
        Worker::draw(g,dst,pos);
 
630
}
 
631
 
 
632
/**
 
633
 *
 
634
 *
 
635
 */
 
636
void Soldier::start_animation (Editor_Game_Base* gg, std::string name, uint time)
 
637
{
 
638
   if (gg->is_game())
 
639
   {
 
640
      start_task_idle ((Game*)gg, get_descr()->get_rand_anim(name), time);
 
641
   }
 
642
}
 
643
 
 
644
/**
 
645
===============
 
646
Soldier::start_task_gowarehouse
 
647
 
 
648
Get the soldier to move to the nearest warehouse.
 
649
The soldier is added to the list of usable wares, so he may be reassigned to
 
650
a new task immediately.
 
651
===============
 
652
*/
 
653
void Soldier::start_task_gowarehouse(Game* g)
 
654
{
 
655
        assert(!m_supply);
 
656
 
 
657
        push_task(g, &taskGowarehouse);
 
658
 
 
659
        m_supply = (IdleWorkerSupply*) new IdleSoldierSupply(this);
 
660
}
 
661
 
 
662
/**
 
663
 * LaunchAttack task
 
664
 *
 
665
 *
 
666
 */
 
667
 
 
668
Bob::Task Soldier::taskLaunchAttack = {
 
669
   "launchattack",
 
670
 
 
671
   (Bob::Ptr)&Soldier::launchattack_update,
 
672
   (Bob::Ptr)&Soldier::launchattack_signal,
 
673
   0,
 
674
};
 
675
 
 
676
/**
 
677
 * soldier::start_task_launchattack
 
678
 */
 
679
void Soldier::start_task_launchattack(Game* g, Flag* f)
 
680
{
 
681
   assert (f);
 
682
 
 
683
   if (f->get_owner() == get_owner())
 
684
      return;
 
685
   
 
686
   
 
687
log ("Soldier::start_task_launchattack\n");
 
688
   push_task(g, &taskLaunchAttack);
 
689
 
 
690
   State* s = get_state();
 
691
 
 
692
   // First step (we must exit from building), and set what is the target
 
693
   s->ivar1 = 1; 
 
694
   s->ivar2 = 0;     // Not requested to attack (used by signal 'combat')
 
695
   s->objvar1 = get_location(g);   // objvar1 is the owner flag (where is attached the FRIEND military site)
 
696
   s->coords = f->get_position(); // Destination
 
697
}
 
698
 
 
699
 
 
700
/**
 
701
 * soldier::launchattack_update
 
702
 */
 
703
void Soldier::launchattack_update (Game* g, State* state)
 
704
{
 
705
   std::string signal = get_signal();
 
706
 
 
707
molog("[launchattack]: Task Updated %d\n", __LINE__);
 
708
   
 
709
/*   if (signal == "combat" || state->ivar2 == 1)
 
710
   {
 
711
      molog("[launchattack] Combat requested for '%s'\n", signal.c_str());
 
712
      set_signal("");
 
713
      state->ivar2 = 1;
 
714
      molog("[launchattack] Combat not found, continue with launchattack\n");
 
715
      state->ivar2 = 0;
 
716
   }
 
717
   if (signal == "fail")
 
718
   {
 
719
      molog("[launchattack]: Caught signal '%s'\n", signal.c_str());
 
720
      set_signal("");
 
721
   }
 
722
   else if (signal.size())
 
723
   {
 
724
      molog("[launchattack]: Interrupted by signal '%s'\n", signal.c_str());
 
725
      pop_task(g);
 
726
      return;
 
727
   }*/
 
728
   
 
729
   // See if it's at building and drop of it
 
730
   if (state->ivar1 == 1)
 
731
   {
 
732
      BaseImmovable* position = g->get_map()->get_immovable(get_position());
 
733
 
 
734
      if (position && position->get_type() == BUILDING) 
 
735
      {
 
736
         // We are in our building, try to exit
 
737
         if (start_task_waitforcapacity(g, (Flag*)get_location(g)->get_base_flag()))
 
738
            return;
 
739
         state->ivar1 = 2;
 
740
         start_task_leavebuilding (g, 1);
 
741
         return;
 
742
      }
 
743
   }
 
744
   
 
745
   // Ensures that the owner of this is the base flag of the militarysite that launchs the attack
 
746
   Map* map = g->get_map();
 
747
   PlayerImmovable* location = get_location(g);
 
748
   Flag* owner;
 
749
 
 
750
   assert(location);
 
751
   assert(location->get_type() == FLAG);
 
752
 
 
753
   owner = (Flag*)location;
 
754
 
 
755
   if (state->ivar1 > 0)
 
756
   {
 
757
      Flag* f_target;
 
758
      Coords c_target;
 
759
      
 
760
      location = (PlayerImmovable*) map->get_immovable(state->coords);
 
761
      
 
762
      assert (location);
 
763
      assert (location->get_type() == FLAG);
 
764
      
 
765
      f_target = (Flag*) location;
 
766
      c_target = f_target->get_position();
 
767
      
 
768
         // Time to return home (in future, time to enter enemu house)
 
769
      if (get_position() == c_target)
 
770
      {
 
771
         Building* bs = f_target->get_building();
 
772
            // If there are enemy soldiers, time to kill they !!!
 
773
         if (start_task_waitforassault(g, bs))
 
774
            return;
 
775
         
 
776
            // Now, this soldier will enter to the house!
 
777
         if (bs->get_owner() == get_owner())
 
778
         {
 
779
            state->ivar1 = 0;
 
780
            schedule_act (g, 10);
 
781
            return;
 
782
         }
 
783
         molog ("Hey\n");
 
784
         bs->conquered_by (get_owner());
 
785
         molog ("Hey\n");
 
786
         state->ivar1 = 0;       // This makes return to home flag
 
787
         schedule_act(g, 50);    // Waits a little before trying to enter to the house
 
788
         return;
 
789
      }
 
790
      
 
791
      // Move towards enemy flag
 
792
      if (!start_task_movepath(g, c_target, 0, get_descr()->get_right_walk_anims(does_carry_ware())))
 
793
      {
 
794
         molog("[launchattack]: Couldn't find path to enemy flag!\n");
 
795
         set_signal("fail");
 
796
         mark(false);   // Now can be healed
 
797
         pop_task(g);
 
798
         return;
 
799
      }
 
800
      else
 
801
         return;
 
802
   }
 
803
   
 
804
   // Return to friend owner flag
 
805
   if (get_position() == owner->get_position())
 
806
   {
 
807
      molog("[launchattack]: We are on home!\n");
 
808
      mark(false);   // Now can be healed
 
809
      pop_task(g);
 
810
      return;
 
811
   }
 
812
   
 
813
   molog ("[launchattack]: Return home\n");
 
814
   if (!start_task_movepath(g, owner->get_position(), 0, get_descr()->get_right_walk_anims(does_carry_ware())))
 
815
   {
 
816
      molog("[launchattack]: Couldn't find path home\n");
 
817
      set_signal("fail");
 
818
      mark(false);   // Now can be healed
 
819
      pop_task(g);
 
820
      return;
 
821
   }
 
822
}
 
823
 
 
824
void Soldier::launchattack_signal (Game* g, State* state)
 
825
{
 
826
   std::string signal = get_signal ();
 
827
   
 
828
   molog ("[LaunchAttack] Interrupted by signal '%s'\n", signal.c_str());
 
829
   set_signal("");
 
830
   mark(false);   // Now can be healed
 
831
   state->ivar1 = 0;
 
832
   launchattack_update(g, state);
 
833
   //pop_task(g);
 
834
}
 
835
 
 
836
/**
 
837
 * WaitForAssault task
 
838
 *
 
839
 *
 
840
 */
 
841
 
 
842
Bob::Task Soldier::taskWaitForAssault = {
 
843
   "waitforassault",
 
844
 
 
845
   (Bob::Ptr)&Soldier::waitforassault_update,
 
846
   (Bob::Ptr)&Soldier::waitforassault_signal,
 
847
   0,
 
848
};
 
849
 
 
850
/**
 
851
 * soldier::start_task_waitforassault (building)
 
852
 *
 
853
 * Returns true if is needed to wait.
 
854
 */
 
855
bool Soldier::start_task_waitforassault (Game* g, Building* b)
 
856
{
 
857
   assert (g);
 
858
   if (!b)
 
859
      return false;
 
860
   assert (b);
 
861
   
 
862
   if (!b->has_soldiers())
 
863
      return false;
 
864
 
 
865
   push_task(g, &taskWaitForAssault);
 
866
   
 
867
   State* s = get_state();
 
868
 
 
869
   s->objvar1 = b;   
 
870
  return true;
 
871
}
 
872
 
 
873
void Soldier::waitforassault_update (Game* g, State* state)
 
874
{
 
875
   Map_Object* imm = state->objvar1.get(g);
 
876
   
 
877
   assert (imm);
 
878
   assert (imm->get_type() == BUILDING);
 
879
   
 
880
   Building* b = (Building*) imm;
 
881
   
 
882
   if (!b->has_soldiers())
 
883
   {
 
884
      MilitarySite* ms = (MilitarySite*) b;
 
885
      molog("[waitforassault]: House %i (%p) empty of soldiers.\n", ms->get_serial(), ms);
 
886
      if (ms->get_owner() == get_owner())
 
887
      {
 
888
         pop_task(g);
 
889
         return;
 
890
      }
 
891
      ms->conquered_by (get_owner());
 
892
      molog("[waitforassault]: House %i (%p) empty of soldiers.\n", ms->get_serial(), ms);
 
893
      pop_task(g);
 
894
      return;
 
895
   }
 
896
   else
 
897
   {
 
898
      switch (b->get_building_type())
 
899
      {
 
900
         case Building::MILITARYSITE:
 
901
            {
 
902
               MilitarySite* ms = (MilitarySite*) b;
 
903
                  // This should launch a soldier to defend the house !
 
904
               skip_act(g);
 
905
               ms->defend(g, this);
 
906
               break;
 
907
            }
 
908
         case Building::WAREHOUSE:
 
909
            {
 
910
               Warehouse* wh = (Warehouse*) b;
 
911
                  // This should launch a soldier to defend the house !
 
912
               skip_act(g);
 
913
               wh->defend(g, this);
 
914
               break;
 
915
            }
 
916
         default:
 
917
            molog("[waitforassault] Nothing to do with this building!!\n");
 
918
            pop_task (g);
 
919
            send_signal(g, "fail");
 
920
            break;;
 
921
      }
 
922
      return;
 
923
   }
 
924
   
 
925
   schedule_act(g, 50);
 
926
   return;
 
927
}
 
928
 
 
929
void Soldier::waitforassault_signal (Game* g, State* state)
 
930
{
 
931
   std::string signal = get_signal();
 
932
   
 
933
   if (signal == "end_combat")
 
934
   {
 
935
      molog("[WaitForAssault] Caught signal '%s' (Waking up!)\n", signal.c_str());
 
936
      set_signal("");
 
937
      waitforassault_update(g, state);
 
938
      return;
 
939
   }
 
940
   else if (signal == "die")
 
941
   {
 
942
      molog ("[WaitForAssault] Caught signal '%s' (Death!)\n", signal.c_str());
 
943
      schedule_destroy(g);
 
944
      pop_task(g);
 
945
      return;
 
946
   }
 
947
   else  if (signal.size() > 0)
 
948
   {
 
949
      molog ("[WaitForAssault] : Interrupted by signal '%s'\n", signal.c_str());
 
950
      pop_task(g);
 
951
   }
 
952
}
 
953
 
 
954
/**
 
955
 * DefendBuilding task
 
956
 *
 
957
 *
 
958
 */
 
959
 
 
960
Bob::Task Soldier::taskDefendBuilding = {
 
961
   "defendbuilding",
 
962
 
 
963
   (Bob::Ptr)&Soldier::defendbuilding_update,
 
964
   (Bob::Ptr)&Soldier::defendbuilding_signal,
 
965
   0,
 
966
};
 
967
 
 
968
void Soldier::start_task_defendbuilding (Game* g, Building* b, Bob* enemy)
 
969
{
 
970
   molog ("Soldier: start_task_defendbuilding\n");
 
971
   assert (b);
 
972
   assert (enemy);
 
973
   assert (((Building*) get_location(g)) == b);
 
974
   
 
975
   push_task(g, &taskDefendBuilding);
 
976
   mark(true);             // This is for prevent to heal soldiers out of the building
 
977
   State* s = get_state();
 
978
   s->ivar1 = 1;
 
979
   s->ivar2 = b->get_serial();
 
980
   s->objvar1 =  enemy;
 
981
   
 
982
}
 
983
 
 
984
void Soldier::defendbuilding_update (Game* g, State* state)
 
985
{
 
986
   if (get_current_hitpoints() < 1)
 
987
   {
 
988
      molog ("[DefendBuilding] : Ohh! I'm deading!!\n");
 
989
      set_location(0);
 
990
      schedule_destroy (g);
 
991
      pop_task(g);
 
992
      schedule_act(g, 100);
 
993
      return;
 
994
   }
 
995
   
 
996
   if (state->ivar1 == 4)
 
997
   {
 
998
      pop_task(g);   // We finally finish this task
 
999
      start_task_idle(g, 0, -1); // Bind the soldier to the MS, and hide him of the map
 
1000
      mark(false);   // Now the soldier can be healed
 
1001
      return;
 
1002
   }
 
1003
      // 1-. Exit of this MS
 
1004
   if (state->ivar1 == 1)
 
1005
   {
 
1006
      BaseImmovable* position = g->get_map()->get_immovable(get_position());
 
1007
 
 
1008
      if (position && position->get_type() == BUILDING) 
 
1009
      {
 
1010
         // We are in our building, try to exit
 
1011
         if (start_task_waitforcapacity(g, (Flag*)get_location(g)->get_base_flag()))
 
1012
            return;
 
1013
         state->ivar1 = 2;
 
1014
         start_task_leavebuilding (g, 0);
 
1015
         return;
 
1016
      }
 
1017
   }
 
1018
   
 
1019
   // 2-. Create a BattleField with this soldier and attach emeny soldier
 
1020
   if (state->ivar1 == 2)
 
1021
   {
 
1022
      PlayerImmovable* imm = (PlayerImmovable*)state->objvar1.get(g);
 
1023
      Soldier* s;
 
1024
   
 
1025
      assert (imm);
 
1026
      s = (Soldier*) imm;
 
1027
   
 
1028
         // Starts real combat!!
 
1029
      Battle* battle = g->create_battle();
 
1030
      battle->soldiers (this, s);
 
1031
      skip_act(g);
 
1032
      return;
 
1033
   }
 
1034
   
 
1035
     // Here at least the soldier has ended of fighting (with this, the soldier will be healed)
 
1036
   mark(false);
 
1037
   
 
1038
   if (state->ivar1 == 3)
 
1039
   {
 
1040
      // Now return home building !
 
1041
      
 
1042
      // Get the building
 
1043
      Building* build = (Building*)g->get_objects()->get_object(state->ivar2);
 
1044
      if (build)
 
1045
      {
 
1046
         molog ("[DefendBuilding] Returning home (%d)\n", state->ivar2);
 
1047
         state->ivar1 = 4; // Next time  Idle !
 
1048
         set_location(build);
 
1049
         start_task_return(g, false);
 
1050
         return;
 
1051
      }
 
1052
      else
 
1053
      {
 
1054
         molog ("[DefendBuilding] Home (%d) doesn't exists!\n", state->ivar2);
 
1055
         pop_task(g);
 
1056
         return;
 
1057
      }
 
1058
      
 
1059
   }
 
1060
   
 
1061
   molog("[DefendBuilding] End of function reached\n");
 
1062
   pop_task(g);
 
1063
}
 
1064
 
 
1065
void Soldier::defendbuilding_signal (Game* g, State* state)
 
1066
{
 
1067
   std::string signal = get_signal();
 
1068
   if (signal == "end_combat")
 
1069
   {
 
1070
      molog("[DefendBuilding] : Caught signal '%s'\n", signal.c_str());
 
1071
      set_signal("");
 
1072
      state->ivar1 = 3;
 
1073
      defendbuilding_update(g, state);
 
1074
   }
 
1075
   else if (signal == "die")
 
1076
   {
 
1077
      molog("[DefendBuilding] : Caught signal '%s'\n", signal.c_str());
 
1078
      
 
1079
        // Better to add here a start_task_die (usefull too for use at fugitive task)
 
1080
      state->ivar1 = 5;
 
1081
      schedule_destroy(g);
 
1082
      schedule_act(g, 5000);
 
1083
      return;
 
1084
   }
 
1085
   else
 
1086
   {
 
1087
      molog("[DefendBuilding] Interrupted by signal '%s'\n");
 
1088
      pop_task(g);
 
1089
      mark(false);
 
1090
   }
 
1091
}
 
1092
 
 
1093
 
 
1094
void Soldier::log_general_info(Editor_Game_Base* egbase) 
 
1095
{
 
1096
   Worker::log_general_info(egbase);
 
1097
   molog("[Soldier]\n");
 
1098
   molog("Levels: %d/%d/%d/%d\n", m_hp_level, m_attack_level, m_defense_level, m_evade_level);
 
1099
   molog ("HitPoints: %d/%d\n", m_hp_current, m_hp_max);
 
1100
   molog ("Attack :  %d-%d\n", m_min_attack, m_max_attack);
 
1101
   molog ("Defense : %d%%\n", m_defense);
 
1102
   molog ("Evade:    %d%%\n", m_evade);
 
1103
}