initialize.c -> init.c, pathfinding.c -> path.c
[h2d.git] / logic.c
blob7f1507480f85a89553aa3b9759da320297a85e26
3 // change tile type
4 void change_tile(mcrd m){
5 if(mp(m)->type ++ == 4)
6 mp(m)->type = 0;
7 if(worlds[0].selunit) fill_map(worlds[0].selunit);
12 void select_next_unit(){
13 do{
14 if(worlds[0].selunit && worlds[0].selunit != (unit*)l_last(worlds[0].units))
15 worlds[0].selunit = (unit*)l_next(worlds[0].selunit);
16 else
17 worlds[0].selunit = (unit*)l_first(worlds[0].units);
18 }while(worlds[0].selunit->player != player);
19 fill_map(worlds[0].selunit);
24 void select_unit(mcrd m){
25 worlds[0].selunit = mp(m)->unit;
26 fill_map(worlds[0].selunit);
31 void kill_unit(unit * u){
32 mp(u->mcrd)->unit = NULL;
33 if(u == worlds[0].selunit) worlds[0].selunit = NULL;
34 free( l_rem(worlds[0].units, u) );
39 // type: 0-рукопашаня, 1-стрельба, 2-метание, 3-таран
40 // u1 - атакующий, u2 - защищающийся
41 void start_attack(unit * u1, unit * u2, int type) {
42 worlds[0].mode = MODE_ATTACK;
43 worlds[0].attack_u1 = u1;
44 worlds[0].attack_u2 = u2;
45 worlds[0].attack_crd = worlds[0].attack_u2->mcrd;
46 worlds[0].attack_index = 0;
47 mp(worlds[0].attack_u1->mcrd)->unit = NULL;
49 //0-рукопашная
50 if(type==0){
51 worlds[0].attack_stage = 0; // наступление
52 worlds[0].attack_is_shoot = false;
53 worlds[0].attack_is_counter = false;
55 //1-стрельба
56 if(type==1){
57 worlds[0].attack_shoot_index = 0;
58 worlds[0].attack_is_shoot = true;
60 //2-метание
61 if(type==2){
62 /*todo*/;
64 //3-таран
65 if(type==3){
66 /*todo*/;
72 void start_moving(unit * u, mcrd m) {
73 if(mp(m)->cost > u->type->mvp || u->mvp == 0)
74 return;
76 worlds[0].move_unit = u;
77 mp(u->mcrd)->unit = NULL;
79 get_path(m);
80 worlds[0].mode = MODE_MOVE;
81 worlds[0].move_tile = (mnode*)l_first(worlds[0].path);
82 worlds[0].move_index = 0;
87 void finish_movement(){
88 worlds[0].mode = MODE_SELECT;
90 worlds[0].move_unit->mcrd = worlds[0].move_tile->crd;
91 worlds[0].move_unit->scrd = map2scr(worlds[0].move_tile->crd);
92 mp(worlds[0].move_unit->mcrd)->unit = worlds[0].move_unit;
94 if(find_feature(worlds[0].move_unit, FEATURE_IGNR))
95 worlds[0].move_unit->mvp -= mp(worlds[0].move_unit->mcrd)->cost;
96 else
97 worlds[0].move_unit->mvp = 0;
99 clear_path();
100 fill_map(worlds[0].move_unit);
102 worlds[0].move_unit = NULL;
107 void ambush(){
108 mnode * mnd = (mnode*) l_next(worlds[0].move_tile);
109 unit * u = mp(mnd->crd)->unit;
110 if( u && u->player != player){
111 // this unit will be attacked!
112 unit * xxx = worlds[0].move_unit;
113 finish_movement();
114 start_attack(u, xxx, 0);
116 // а можно разрешать окнтратаку, НО
117 // но добавить специальный омдификатор "попал в засаду"
118 // его действие будет прекращаться после первого боя
119 // он будет уменьшать защиту и атаку
121 // стыдно. исправить. что бы враг не ответил!
122 worlds[0].attack_is_counter = 1;
123 return;
129 void move_logic(){
130 if(worlds[0].move_index == STEPS){
131 worlds[0].move_index = 0;
132 worlds[0].move_tile = (mnode*)l_next(worlds[0].move_tile);
133 if(worlds[0].move_tile == (mnode*)l_last(worlds[0].path))
134 finish_movement();
135 else
136 ambush();
138 worlds[0].move_index++;
143 int calc_damage(unit * a, unit * b){
144 a = b;
145 return(4); // random
150 void on_reach_enemy(){
151 int damage = calc_damage(worlds[0].attack_u1, worlds[0].attack_u2);
152 worlds[0].attack_u2->health -= damage;
153 if(worlds[0].attack_u2->health <= 0) {
154 kill_unit(worlds[0].attack_u2);
155 worlds[0].attack_u2 = NULL;
156 fill_map(worlds[0].attack_u1);
158 worlds[0].attack_u1->can_attack = false;
159 // теперь возвращаемся на тайл
160 worlds[0].attack_stage = 1;
165 void try_retreat(){
166 for(int i=0; i<6; i++){
167 //mcrd n = neib(attack_u1->mcrd, i);
168 mcrd n = neib(worlds[0].attack_u1->mcrd, neib2(i));
169 if(!mp(n)->unit){
170 worlds[0].attack_crd = n;
171 worlds[0].attack_stage = 2;
172 return;
179 void start_counterattack(){
180 start_attack(worlds[0].attack_u2, worlds[0].attack_u1, 0);
181 worlds[0].attack_is_counter = true;
186 void on_return_after_attack(){
187 mp(worlds[0].attack_u1->mcrd)->unit = worlds[0].attack_u1;
189 if(worlds[0].attack_is_counter || !worlds[0].attack_u2){
190 if(worlds[0].attack_u1->health < worlds[0].attack_u1->type->health){
191 mp(worlds[0].attack_u1->mcrd)->unit = NULL;
192 worlds[0].attack_crd = worlds[0].attack_u1->mcrd;
193 try_retreat();
194 }else{
195 worlds[0].attack_u1 = worlds[0].attack_u2 = NULL;
196 worlds[0].mode = MODE_SELECT;
198 }else{
199 start_counterattack();
205 void on_done_retreat(){
206 mp(worlds[0].attack_crd)->unit = worlds[0].attack_u1;
207 worlds[0].attack_u1->mcrd = worlds[0].attack_crd;
208 worlds[0].attack_u1 = worlds[0].attack_u2 = NULL;
209 worlds[0].mode = MODE_SELECT;
214 void shoot_attack(){
215 scrd a = worlds[0].attack_u1->scrd;
216 scrd b = worlds[0].attack_u2->scrd;
217 int steps = sdist(a,b) / 6;
219 //стрела долетела
220 if(worlds[0].attack_shoot_index >= steps){
221 int dmg = calc_damage(worlds[0].attack_u1, worlds[0].attack_u2);
222 worlds[0].attack_u2->health -= dmg;
223 if(worlds[0].attack_u2->health <= 0) {
224 kill_unit(worlds[0].attack_u2);
225 fill_map(worlds[0].attack_u1);
227 mp(worlds[0].attack_u1->mcrd)->unit = worlds[0].attack_u1;
228 worlds[0].attack_u1->can_attack = false;
229 worlds[0].attack_u1 = worlds[0].attack_u2 = NULL;
230 worlds[0].mode = MODE_SELECT;
233 worlds[0].attack_shoot_index++;
238 void attack_logic() {
239 if(worlds[0].attack_is_shoot)
240 shoot_attack();
241 else{
242 if(worlds[0].attack_stage==0 && worlds[0].attack_index==STEPS/2+1)
243 on_reach_enemy();
244 if(worlds[0].attack_stage==1 && worlds[0].attack_index==0)
245 on_return_after_attack();
246 if(worlds[0].attack_stage==2 && worlds[0].attack_index==STEPS)
247 on_done_retreat();
249 if(worlds[0].attack_stage==0) worlds[0].attack_index++;
250 if(worlds[0].attack_stage==1) worlds[0].attack_index--;
251 if(worlds[0].attack_stage==2) worlds[0].attack_index++;
257 void logic(){
258 if(worlds[0].mode==MODE_MOVE) move_logic();
259 if(worlds[0].mode==MODE_ATTACK) attack_logic();
264 void updatefog(){
265 FOR_EACH_TILE{
266 mp(mc)->fog=0;
267 FOR_EACH_UNIT{
268 if(u->player == player
269 && mdist(mc, u->mcrd) <= u->type->see)
270 mp(mc)->fog++;