1 /*****************************************************************************
2 ** This is part of the SpaceZero program
3 ** Copyright(C) 2006-2013 MRevenga
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License (version 3), or
7 ** (at your option) any later version, as published by the Free Software
8 ** Foundation.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 ******************************************************************************/
19
20 /************* SpaceZero M.R.H. 2006-2013 ******************
21 Author: MRevenga
22 E-mail: mrevenga at users.sourceforge.net
23 version 0.86 December 2013
24 **************************************************************/
25
26 #include <sys/time.h>
27 #include "objects.h"
28 #include "general.h"
29 #include "functions.h"
30 #include "spacecomm.h"
31 #include "ai.h"
32 #include "data.h"
33 #include "sound.h"
34 #include "sectors.h"
35 #include "locales.h"
36 #include "players.h"
37
38 #define DL (2*RADAR_RANGE)
39 /* #define DL 3000 */
40
41 struct ObjTree *treeobjs=NULL;
42 struct HeadObjList listheadobjs; /* List of all objs */
43 extern struct HeadObjList *listheadkplanets; /* lists of planets known by players */
44 extern struct HeadObjList listheadplayer; /* list of objects of each player */
45 extern struct TextMessageList listheadtext;
46 extern struct CharListHead gameloglist; /* list of all game messages */
47 extern struct Window windowgamelog;
48 extern int actual_player,actual_player0;
49 extern int record;
50 extern int gameover;
51 extern int *cell;
52
53
54 int g_objid=1; /* id of the objects */
55 int g_projid=-2; /* id of the projectiles */
56
57
58
NewObj(int type,int stype,int x,int y,float vx,float vy,int weapontype,int engtype,int player,Object * parent,Object * in)59 Object *NewObj(int type,int stype,
60 int x,int y,float vx,float vy,
61 int weapontype,int engtype,int player,Object *parent,Object *in){
62
63 /*
64 Create new object
65 return:
66 a pointer to the new object
67 NULL if the are some error or if isnot possible to create it.
68 */
69 Object *obj;
70 Weapon *weapon;
71 struct Player *players;
72 int i;
73
74 players=GetPlayers();
75 if(player<0||player>GameParametres(GET,GNPLAYERS,0)+1){
76 fprintf(stderr, "ERROR in NewObj(): invalid player id %d\n", player);
77 fprintf(stderr, "\ttype :%d stype: %d\n", type,stype);
78 exit(-1);
79 }
80
81
82 obj=malloc(sizeof(Object));
83 MemUsed(MADD,+sizeof(Object));
84 if(obj==NULL){
85 fprintf(stderr,"ERROR in malloc NewObj()\n");
86 exit(-1);
87 }
88
89 if(type<TRACKPOINT){
90 players[player].status=PLAYERMODIFIED;
91 if(type==SHIP)listheadplayer.update=1;
92 }
93 if(type<=0){
94 fprintf(stderr,"ERROR in NewObj() (type<0) type:%d stype:%d\n",type,stype);
95 exit(-1);
96 }
97
98 strcpy(obj->name,"x");
99 obj->oriid=0;
100 obj->destid=0;
101 obj->durable=FALSE;
102 obj->visible=TRUE;
103 obj->selected=FALSE;
104 obj->radar=RADAR_RANGE;
105 obj->experience=0;
106 obj->pexperience=0;
107 obj->modified=SENDOBJNEW;
108 obj->ttl=0;
109 obj->level=0;
110 obj->kills=0;
111 obj->ntravels=0;
112 obj->habitat=H_SPACE;
113 obj->mode=NAV;
114 obj->damage=1;
115 obj->x=x;obj->y=y; /* actual position */
116 obj->x0=x;obj->y0=y; /* speed in the previous time */
117 obj->vx=vx,obj->vy=vy; /* actual speed */
118 obj->fx0=obj->fy0=0; /* force in previous time */
119 obj->fx=obj->fy=0; /* actual force */
120 obj->a=0; /* ship angle */
121 obj->ang_v=0; /* angular speed */
122 obj->ang_a=0; /* angular aceleration */
123 obj->accel=0; /* aceleracion */
124 obj->gas=0; /* combustible */
125 obj->gas_max=0; /* max. combustible */
126 obj->life=1; /* life time */
127 obj->shield=0; /* shield (0,1) */
128 obj->state=1; /* ship state (0,1)*/
129
130 switch(type){
131 case PLANET:
132 obj->id=g_objid; /* identifier */
133 break;
134 case PROJECTILE:
135 obj->id=GetNProc()*g_projid-GetProc(); /* identifier */
136 break;
137 default:
138 obj->id=GetNProc()*g_objid+GetProc(); /* identifier */
139 break;
140 }
141
142
143 obj->dest_r2=-1; /* distance2 of the nearest object */
144 obj->parent=parent; /* id of the creator obj */
145 obj->dest=NULL; /* pointer to nearest object */
146 obj->in=in; /* pointer to container object */
147 obj->mass=1; /* mass */
148 obj->items=0;
149
150 obj->radio=1; /* radio */
151 obj->type=type; /* object type */
152 obj->subtype=stype; /* object subsubtype */
153 obj->player=player;
154
155 obj->ai=0; /* 0: by keyboard. [1,10] */
156 obj->sw=0;
157 obj->lorder=NULL;
158 obj->actorder.id=-1;
159 obj->trace=FALSE;
160 obj->norder=0;
161
162 obj->cargo.capacity=0; /* max. cargo capacity */
163 obj->cargo.mass=0; /* actual mass cargo */
164 obj->cargo.n=0; /* number of elements */
165 obj->cargo.hlist=NULL; /* list to object in cargo */
166
167 obj->planet=NULL;
168
169 NewWeapon(&obj->weapon0,weapontype);
170 NewWeapon(&obj->weapon1,CANNON0);
171 NewWeapon(&obj->weapon2,CANNON0);
172
173 if(obj->type==SHIP && obj->subtype==TOWER){
174 obj->weapon0.projectile.gascost*=8;
175 obj->weapon1.projectile.gascost*=8;
176 obj->weapon2.projectile.gascost*=8;
177 }
178
179 obj->weapon=&obj->weapon0;
180
181 NewEngine(&obj->engine,engtype);
182 obj->cdata=NULL;
183
184 switch(obj->type){
185 case PLANET:
186 obj->pid=obj->id;
187 g_objid++;
188 break;
189 case TRACE:
190 obj->id=-1;
191 obj->modified=SENDOBJNOTSEND;
192 break;
193 case PROJECTILE:
194 obj->pid=obj->id;
195 g_projid--;
196 if(obj->subtype==EXPLOSION){
197 obj->modified=SENDOBJNOTSEND;/* don't send explosion */
198 }
199 break;
200 default:
201 obj->pid=players[obj->player].pid;
202 players[obj->player].pid++;
203 g_objid++;
204 break;
205 }
206 switch(obj->type){
207
208 case PROJECTILE:
209 obj->radar=0;
210 obj->planet=NULL;/* obj->parent->planet; */
211 obj->in=in;
212
213 if(obj->parent==NULL){
214 fprintf(stderr,"ERROR (NewObj) parent NULL id: %d\n",obj->id);
215 fprintf(stderr,"\tplayer: %d\n",obj->player);
216 fprintf(stderr,"\ttype: %d\n",obj->type);
217 fprintf(stderr,"\tstype: %d\n",obj->subtype);
218 return(NULL);
219 }
220
221 obj->habitat=obj->parent->habitat;
222
223 switch(stype){
224 case SHOT1: /* standard */
225 obj->state=1;
226 obj->radio=1;
227 weapon=&obj->parent->weapon0;
228 obj->durable=weapon->projectile.durable;
229 obj->life=weapon->projectile.life;
230 obj->damage=weapon->projectile.damage;
231 obj->mass=weapon->projectile.mass;
232 break;
233 case MISSILE: /* SHOT3 */
234 obj->radar=.5*RADAR_RANGE;
235 obj->state=1;
236 obj->gas_max=100;
237 obj->gas=obj->gas_max;
238 obj->radio=6;
239 obj->level=parent->level;
240 weapon=&obj->parent->weapon1;
241 obj->durable=weapon->projectile.durable;
242 obj->life=weapon->projectile.life;
243 obj->damage=weapon->projectile.damage;
244 obj->mass=weapon->projectile.mass;
245 break;
246 case LASER: /* shot4 */
247 obj->state=1;
248 obj->gas_max=0;
249 obj->radio=50;
250 weapon=&obj->parent->weapon2;
251 obj->durable=weapon->projectile.durable;
252 obj->life=weapon->projectile.life;
253 obj->damage=weapon->projectile.damage;
254 obj->mass=weapon->projectile.mass;
255 break;
256 case EXPLOSION:
257 obj->durable=TRUE;
258 obj->life=LIFEEXPLOSION;
259 obj->damage=obj->parent->damage/16;
260 obj->parent=NULL;
261 obj->mass=5;
262 break;
263 default:
264 fprintf(stderr,"ERROR (NewOb).Not implemented\n");
265 exit(-1);
266 break;
267 }
268
269 break;
270 case SHIP:
271 /* g_print("creando...%d...",GetTime()); */
272 ShipProperties(obj,obj->subtype,in);
273 break;
274
275 case ASTEROID:
276 obj->durable=TRUE;
277 obj->life=LIFEASTEROID+LIFEASTEROID*rand()/RAND_MAX/2.0;
278 obj->state=10;
279 obj->a=0;
280 obj->ang_v=(2.0*Random(-1)-1.0)/5.0;
281
282 switch(obj->subtype){
283 case ASTEROID1:
284 obj->mass=100;
285 obj->damage=100;
286 obj->radio=36;
287 break;
288 case ASTEROID2:
289 obj->mass=30;
290 obj->damage=50;
291 obj->radio=18;
292 obj->life/=2;
293 break;
294 case ASTEROID3:
295 obj->mass=10;
296 obj->damage=25;
297 obj->radio=10;
298 obj->life/=4;
299 break;
300 default:
301 fprintf(stderr,"ERROR in NewObj(): asteroid subtype %d no implemented\n",
302 obj->subtype);
303 exit(-1);
304 break;
305 }
306 break;
307
308 case PLANET:
309 obj->mass=(int)((MINPLANETMASS+(MAXPLANETMASS-MINPLANETMASS)*
310 Random(-1))/1000)*1000;
311 obj->radio=pow(obj->mass,.333);
312 obj->shield=1.0;
313 obj->state=100;
314 obj->damage=10000;
315 obj->planet=NewPlanet();
316 obj->planet->x=obj->x;
317 obj->planet->y=obj->y;/*-obj->radio*2; */
318 obj->planet->r=obj->radio;
319 obj->planet->gold=(int)((MINPLANETGOLD+((MAXPLANETGOLD-MINPLANETGOLD)*
320 Random(-1))*(float)obj->mass/MAXPLANETMASS)*RESOURCEFACTOR);
321 obj->planet->reggold=0.035*((float)obj->mass/MAXPLANETMASS)+0.02+0.02*(Random(-1));
322 obj->planet->A=0;
323 obj->planet->B=0;
324 break;
325 case TRACKPOINT:
326 obj->durable=FALSE;
327 obj->visible=FALSE;
328 obj->damage=0;
329 obj->mass=0;
330 obj->shield=0;
331 break;
332 case TRACE:
333 obj->durable=TRUE;
334 obj->life=LIFETRACE;
335 obj->gas=0;
336 if(obj->parent!=NULL){
337 obj->habitat=obj->parent->habitat;
338 obj->in=in;
339 }
340 break;
341 default:
342 fprintf(stderr,"ERROR (NewOb)\n");
343 exit(-1);
344 break;
345 }
346
347 obj->cost*=COSTFACTOR;
348
349 /* data base */
350 if(obj->type==SHIP){ /* HERE TODO SHIP COMPUTER, only ships */
351 obj->cdata=malloc(sizeof(Data));
352 MemUsed(MADD,+sizeof(Data));
353 if(obj->cdata==NULL){
354 fprintf(stderr,"ERROR in malloc NewObj()\n");
355 exit(-1);
356 }
357 for(i=0;i<4;i++){
358 obj->cdata->obj[i]=NULL;
359 obj->cdata->d2[i]=-1;
360 obj->cdata->td2[i]=0;
361 }
362 obj->cdata->mlevel=0;
363 obj->cdata->tmlevel=0;
364 obj->cdata->a=0;
365 obj->cdata->b=0;
366 }
367 return(obj);
368 } /* --Newobj() */
369
Add2ObjList(struct HeadObjList * lhead,Object * obj)370 int Add2ObjList(struct HeadObjList *lhead,Object *obj){
371 /*
372 add obj to the list lhead
373 */
374
375 switch(obj->type){
376
377 case SHIP:
378 case PLANET:
379 return(Add2ObjList_E(lhead,obj));
380 break;
381 case PROJECTILE:
382 case ASTEROID:
383 case ARTEFACT:
384 case TRACKPOINT:
385 case TRACE:
386 return(Add2ObjList_B(lhead,obj));
387 break;
388 default:
389 fprintf(stderr,"ERROR in Ass2ObjList(): type unknown\n");
390 exit(-1);
391 break;
392 }
393 }
394
395
Add2ObjList_B(struct HeadObjList * lhead,Object * obj)396 int Add2ObjList_B(struct HeadObjList *lhead,Object *obj){
397 /*
398 add obj at the beginning of the list
399 */
400
401 struct ObjList *ls;
402
403 ls=lhead->list;
404
405 lhead->list=malloc(sizeof(struct ObjList));
406 MemUsed(MADD,+sizeof(struct ObjList));
407 if(lhead->list==NULL){
408 fprintf(stderr,"ERROR in malloc Add2ObjList()\n");
409 exit(-1);
410 }
411
412 lhead->list->obj=obj;
413 lhead->n++;
414 lhead->list->next=ls;
415 return(0);
416 }
417
Add2ObjList_E(struct HeadObjList * lhead,Object * obj)418 int Add2ObjList_E(struct HeadObjList *lhead,Object *obj){
419 /*
420 add obj at the end of the list
421 */
422
423 struct ObjList *ls;
424
425
426 if(lhead->list==NULL){ /* first item */
427 return(Add2ObjList_B(lhead,obj));
428 }
429 else{
430 ls=lhead->list;
431 while(ls->next!=NULL){
432 ls=ls->next;
433 }
434
435 ls->next=malloc(sizeof(struct ObjList));
436 MemUsed(MADD,+sizeof(struct ObjList));
437 if(ls->next==NULL){
438 fprintf(stderr,"ERROR in malloc Add2ObjList()\n");
439 exit(-1);
440 }
441
442 ls->next->obj=obj;
443 ls->next->next=NULL;
444 lhead->n++;
445 }
446
447 return(0);
448 }
449
450
NewWeapon(Weapon * weapon,int type)451 void NewWeapon(Weapon *weapon,int type){
452 /*
453 Create a weapon of type type
454 returns:
455 a pointer to the new weapon.
456 */
457 weapon->type=type;
458
459 switch (type){
460 case CANNON0: /* no weapon */
461 weapon->projectile.type=SHOT0;
462 weapon->rate=10000;
463 weapon->nshots=0;
464 weapon->cont1=weapon->rate;
465 weapon->mass=0;
466 weapon->n=0;
467 weapon->max_n=0;
468 break;
469 case CANNON1:
470 weapon->projectile.type=SHOT1;
471 weapon->rate=20;
472 weapon->nshots=1;
473 weapon->cont1=weapon->rate;
474 weapon->mass=0;
475 weapon->n=0;
476 weapon->max_n=50;
477 break;
478 case CANNON2:
479 weapon->projectile.type=SHOT1;
480 weapon->rate=15;
481 weapon->nshots=1;
482 weapon->cont1=weapon->rate;
483 weapon->mass=0;
484 weapon->n=0;
485 weapon->max_n=50;
486 break;
487 case CANNON3:
488 weapon->projectile.type=SHOT1;
489 weapon->rate=12;
490 weapon->nshots=1;
491 weapon->cont1=weapon->rate;
492 weapon->mass=0;
493 weapon->n=0;
494 weapon->max_n=50;
495 break;
496 case CANNON4:
497 weapon->projectile.type=SHOT1;
498 weapon->rate=12;
499 weapon->nshots=2;
500 weapon->cont1=weapon->rate;
501 weapon->mass=0;
502 weapon->n=0;
503 weapon->max_n=50;
504 break;
505 case CANNON5:
506 weapon->projectile.type=SHOT1;
507 weapon->rate=8;
508 weapon->nshots=3;
509 weapon->cont1=weapon->rate;
510 weapon->mass=0;
511 weapon->n=0;
512 weapon->max_n=150;
513 break;
514 case CANNON6:
515 weapon->projectile.type=SHOT1;
516 weapon->rate=8;
517 weapon->nshots=5;
518 weapon->cont1=weapon->rate;
519 weapon->mass=0;
520 weapon->n=0;
521 weapon->max_n=50;
522 break;
523 case CANNON7:
524 weapon->projectile.type=SHOT1;
525 weapon->rate=8;
526 weapon->nshots=6;
527 weapon->cont1=weapon->rate;
528 weapon->mass=0;
529 weapon->n=0;
530 weapon->max_n=50;
531 break;
532 case CANNON8:
533 weapon->projectile.type=MISSILE;/* SHOT3; */
534 weapon->rate=80;
535 weapon->nshots=1;
536 weapon->cont1=weapon->rate;
537 weapon->mass=0;
538 weapon->n=0;
539 weapon->max_n=4;
540 break;
541 case CANNON9: /* laser */
542 weapon->projectile.type=LASER;/* SHOT4 */
543 weapon->rate=10;
544 weapon->nshots=1;
545 weapon->cont1=weapon->rate;
546 weapon->mass=0;
547 weapon->n=0;
548 weapon->max_n=25;
549
550 break;
551 default:
552 printf("error (NewWeapon) type: %d\n",type);
553 exit(-1);
554 break;
555 }
556
557 switch(weapon->projectile.type){
558 case SHOT0: /* no weapon */
559 weapon->projectile.durable=TRUE;
560 weapon->projectile.life=0;
561 weapon->projectile.damage=0;
562 weapon->projectile.max_vel=0;
563 weapon->projectile.mass=0;
564 weapon->projectile.gascost=0;
565 weapon->projectile.unitcost=0;
566 break;
567 case SHOT1:
568 weapon->projectile.durable=TRUE;
569 weapon->projectile.life=LIFESHOT1;
570 weapon->projectile.damage=15*DAMAGEFACTOR;
571 weapon->projectile.max_vel=VELMAX*.75;
572 weapon->projectile.mass=1;
573 weapon->projectile.gascost=6;
574 weapon->projectile.unitcost=.25;
575 break;
576 case SHOT2:
577 weapon->projectile.durable=TRUE;
578 weapon->projectile.life=LIFESHOT2;
579 weapon->projectile.damage=25*DAMAGEFACTOR;
580 weapon->projectile.max_vel=VELMAX*.85;
581 weapon->projectile.mass=2;
582 weapon->projectile.gascost=10;
583 weapon->projectile.unitcost=2;
584 break;
585 case MISSILE:/* SHOT3: missile */
586 weapon->projectile.durable=TRUE;
587 weapon->projectile.life=LIFESHOT3;
588 weapon->projectile.damage=75*DAMAGEFACTOR;
589 weapon->projectile.max_vel=VELMAX*.85;
590 weapon->projectile.mass=15;
591 weapon->projectile.gascost=10;
592 weapon->projectile.unitcost=50;
593 break;
594 case LASER:/* SHOT4: laser */
595 weapon->projectile.durable=TRUE;
596 weapon->projectile.life=LIFESHOT4;
597 weapon->projectile.damage=50*DAMAGEFACTOR;
598 weapon->projectile.max_vel=2*VELMAX;
599 weapon->projectile.mass=0;
600 weapon->projectile.gascost=30;
601 weapon->projectile.unitcost=2;
602 break;
603 default:
604 break;
605
606 }
607 }
608
NewEngine(Engine * eng,int type)609 void NewEngine(Engine *eng,int type){
610 /*
611 Create in eng a new engine of type type.
612 */
613
614 /*
615 typedef struct{
616 int type;
617 int a_max; max accel
618 int a; increment of acceleration
619 int v_max; max speed
620 int v2_max; max speed 2
621 float ang_a; increment angular acceleration
622 float ang_a_max; max angular acceleration
623 float ang_v_max; max angular velocity
624 float gascost; cost of gas
625 int mass; mass of the engine
626 }Engine;
627 */
628
629
630 /* default for all engines */
631
632 eng->type=type;
633 switch (type){
634 case ENGINE0: /* no engine */
635 eng->a=0;
636 eng->ang_a=0;
637 eng->a_max=0;
638 eng->v_max=0;
639 eng->ang_a=0;
640 eng->ang_a_max=0;
641 eng->ang_v_max=0;
642 eng->gascost=0;
643 eng->mass=0;
644 break;
645 case ENGINE1:
646 eng->a=0;
647 eng->a_max=0;
648 eng->v_max=20;/* VELMAX; 15; */
649 eng->ang_a=0.01;
650 eng->ang_a_max=.2;
651 eng->ang_v_max=0.3;
652 eng->gascost=.05;
653 eng->mass=10;
654 break;
655 case ENGINE2:
656 eng->a=25;
657 eng->a_max=200;
658 eng->v_max=40;/* 40VELMAX; 15; */
659 eng->ang_a=0.001; /* .0004 missile */
660 eng->ang_a_max=.2;/* .2 */
661 eng->ang_v_max=.3;/* .3 */
662 eng->gascost=.07;
663 eng->mass=20;
664 break;
665 case ENGINE3:
666 eng->a=35;
667 eng->a_max=400;
668 eng->v_max=22;/* VELMAX; 20; */
669 eng->ang_a=0.02;
670 eng->ang_a_max=.2;
671 eng->ang_v_max=0.3;
672 eng->gascost=.07;
673 eng->mass=30;
674 break;
675 case ENGINE4:
676 eng->a=45;
677 eng->a_max=600;
678 eng->v_max=24;/* VELMAX; 25; */
679 eng->ang_a=0.03;
680 eng->ang_a_max=.2;
681 eng->ang_v_max=0.3;
682 eng->gascost=.11;
683 eng->mass=40;
684 break;
685 case ENGINE5:
686 eng->a=55;
687 eng->a_max=1200;
688 eng->v_max=24;/* VELMAX; 30; */
689 eng->ang_a=0.04;
690 eng->ang_a_max=.2;
691 eng->ang_v_max=0.3;
692 eng->gascost=.16;
693 eng->mass=60;
694 break;
695 case ENGINE6:
696 eng->a=55;
697 eng->a_max=1400;
698 eng->v_max=20;/* VELMAX; 30; */
699 eng->ang_a=0.04;
700 eng->ang_a_max=.2;
701 eng->ang_v_max=0.3;
702 eng->gascost=.18;
703 eng->mass=80;
704 break;
705
706 default:
707 printf("error (NewEngine) type: %d\n",type);
708 exit(-1);
709 break;
710 }
711
712 eng->v2_max=eng->v_max*eng->v_max;
713 }
714
715
CountObjs(struct HeadObjList * lh,int player,int type,int subtype)716 int CountObjs(struct HeadObjList *lh,int player,int type,int subtype){
717 /*
718 Count the number of objects of type type.
719 return this value.
720 */
721
722 struct ObjList *ls;
723 int n=0;
724
725 if(player!=-1){
726
727 if(type==-1){
728 ls=lh->list;
729 while(ls!=NULL){
730 if(ls->obj->player!=player){ls=ls->next;continue;}
731 if(ls->obj->state<=0){ls=ls->next;continue;}
732 n++;
733 ls=ls->next;
734 }
735 return(n);
736 }
737
738 if(subtype==-1){
739 ls=lh->list;
740 while(ls!=NULL){
741 if(ls->obj->player!=player){ls=ls->next;continue;}
742 if(ls->obj->state<=0){ls=ls->next;continue;}
743 if(ls->obj->type==type)n++;
744 ls=ls->next;
745 }
746 return(n);
747 }
748
749 ls=lh->list;
750 while(ls!=NULL){
751 if(ls->obj->player!=player){ls=ls->next;continue;}
752 if(ls->obj->state<=0){ls=ls->next;continue;}
753 if(ls->obj->type==type && ls->obj->subtype==subtype)n++;
754 ls=ls->next;
755 }
756 return(n);
757 }
758
759 /* player==-1 count for all players */
760
761 if(type==-1){
762 ls=lh->list;
763 while(ls!=NULL){
764 if(ls->obj->state<=0){ls=ls->next;continue;}
765 n++;
766 ls=ls->next;
767 }
768 return(n);
769 }
770
771 if(subtype==-1){
772 ls=lh->list;
773 while(ls!=NULL){
774 if(ls->obj->state<=0){ls=ls->next;continue;}
775 if(ls->obj->type==type)n++;
776 ls=ls->next;
777 }
778 return(n);
779 }
780
781 ls=lh->list;
782 while(ls!=NULL){
783 if(ls->obj->state<=0){ls=ls->next;continue;}
784 if(ls->obj->type==type && ls->obj->subtype==subtype)n++;
785 ls=ls->next;
786 }
787 return(n);
788 }
789
790
CountModObjs(struct HeadObjList * lh,int type)791 int CountModObjs(struct HeadObjList *lh,int type){
792 /*
793 Count the number of modified objects of type type.
794 return this value.
795 note: not used
796 */
797
798 struct ObjList *ls;
799 int n=0;
800
801 ls=lh->list;
802 while(ls!=NULL){
803 if(ls->obj->type==type && ls->obj->modified!=SENDOBJUNMOD){
804 n++;
805 }
806 ls=ls->next;
807 }
808 return n;
809 }
810
811
RemoveDeadObjs(struct HeadObjList * lhobjs,Object * cv0)812 Object *RemoveDeadObjs(struct HeadObjList *lhobjs , Object *cv0){
813 /*
814 version 0.3
815 Remove all dead objects from the list lhobjs.
816 in net only are remove objects with modified=SENDOBJDEAD
817 in single game remove obj with state<=0
818 return:
819 cv0 if is not removed
820 NULL if cv0 is removed
821 */
822
823 struct ObjList *ls,*freels;
824 Object *ret;
825 char text[MAXTEXTLEN];
826 int swdead=0;
827 int swx=0;
828 int gnet;
829 struct Player *players;
830
831 ret=cv0;
832 gnet=GameParametres(GET,GNET,0);
833 players=GetPlayers();
834
835 ls=lhobjs->list;
836 while(ls!=NULL){
837 freels=NULL;
838 swdead=0;
839 swx=0;
840 if(gnet==TRUE){
841 if(ls->obj->modified==SENDOBJDEAD){swdead=1;}
842 }
843 else{
844 if(ls->obj->state<=0){swdead=1;}
845 }
846
847 if(ls->obj->type==PROJECTILE && ls->obj->subtype==MISSILE && ls->obj->state<=0){
848 swdead=1;
849 }
850
851 if(swdead){
852 if(ls->obj->type<TRACKPOINT){
853 int player=ls->obj->player;
854 players[player].status=PLAYERMODIFIED;
855 if(ls->obj->type==SHIP && player==actual_player)listheadplayer.update=1;
856 }
857
858 freels=ls;
859
860 switch(ls->obj->type){
861 case ASTEROID:
862 swx=1;
863
864 if(ls->obj->habitat==H_PLANET && ls->obj->sw==0){ /* asteroid crashed */
865 ls->obj->in->planet->gold+=100*pow(2,5-ls->obj->subtype);
866 }
867
868 break;
869 case SHIP:
870 swx=1;
871 if(ls->obj->mode==SOLD)swx=0;
872 if(ls->obj->habitat==H_PLANET && swx){
873
874 if(ls->obj->sw!=0){ /* ship killed */
875 ls->obj->in->planet->gold+=0.025*GetPrice(ls->obj,0,0,0);
876 }
877 else{ /* ship crashed */
878 float price,factor;
879 factor=0.01*ls->obj->state*0.25;
880 if(factor<.1)factor=.1; /* at least an 10 percent*/
881 price=factor*GetPrice(ls->obj,0,0,0);
882 ls->obj->in->planet->gold+=price;
883 }
884 }
885
886 break;
887 case PROJECTILE:
888 if(ls->obj->subtype==MISSILE){
889 swx=1;
890 }
891 break;
892 default:
893 break;
894 }
895
896 if(swx){
897 Explosion(lhobjs,cv0,ls->obj,0); /* create new objects, doesnot change ls*/
898 #if SOUND
899 Play(ls->obj,EXPLOSION0,1);
900 #endif
901 }
902 }
903
904 if(freels!=NULL){
905 if(freels->obj->type < TRACKPOINT) {
906 players[freels->obj->player].status=PLAYERMODIFIED;
907 }
908 if(freels->obj->type==SHIP){
909 switch(freels->obj->subtype){
910 case EXPLORER:
911 case FIGHTER:
912 case QUEEN:
913 case FREIGHTER:
914 case TOWER:
915 case PILOT:
916 players[freels->obj->player].ndeaths++;
917 break;
918 case SATELLITE:
919 case GOODS:
920 break;
921 default:
922 fprintf(stderr,"ERROR in RemoveDeadObjs(): Unknown subtype: %d\n",
923 freels->obj->subtype);
924 exit(-1);
925 break;
926 }
927 if( freels->obj->player == actual_player && freels->obj->mode!=SOLD){
928 snprintf(text,MAXTEXTLEN,"(%c %d) %s",Type(freels->obj),freels->obj->pid,GetLocale(L_SHIPDESTROYED));
929 if(!Add2TextMessageList(&listheadtext,text,freels->obj->id,freels->obj->player,0,100,0)){
930 Add2CharListWindow(&gameloglist,text,0,&windowgamelog);
931 }
932 }
933 }
934
935 if(freels->obj->subtype==QUEEN){
936 int gqueen;
937 if(freels->obj->player == actual_player){
938 printf("%s\n",GetLocale(L_QUEENDESTROYED));
939 }
940 gqueen=GameParametres(GET,GQUEEN,0);
941
942 if(gqueen==TRUE){
943 DestroyAllPlayerObjs(lhobjs,freels->obj->player);
944 if(freels->obj->player==actual_player0)gameover=TRUE;
945 }
946 }
947 }
948
949 ls=ls->next;
950
951 if(freels!=NULL){
952 if(freels->obj==cv0)ret=NULL;
953 RemoveObj(lhobjs,freels->obj);
954 }
955 }
956 return(ret);
957 }
958
959
RemoveObj(struct HeadObjList * lhobjs,Object * obj2remove)960 void RemoveObj(struct HeadObjList *lhobjs,Object *obj2remove){
961 /*
962 Remove the object obj2remove from system.
963 */
964
965 struct ObjList *ls,*ls0,*ls1,*freels;
966 Object *obj;
967
968 if(obj2remove==NULL){
969 fprintf(stderr,"ERROR en removeobj(), obj is NULL\n");
970 return;
971 }
972
973 freels=NULL;
974 ls=lhobjs->list;
975 ls0=lhobjs->list;
976
977 while(ls->obj!=obj2remove && ls!=NULL){
978 ls0=ls;
979 ls=ls->next;
980 }
981 if(ls->obj==obj2remove){
982 if(ls != ls0){
983 freels=ls;
984 ls0->next=ls0->next->next;
985 ls=ls->next;
986 }
987 else{ /* its the first element */
988 freels=ls;
989 lhobjs->list=lhobjs->list->next;
990 ls=ls->next;
991 ls0=ls->next;
992 }
993
994 /* cleaning the memory and references */
995
996 obj=freels->obj;
997 ls1=lhobjs->list;
998 while(ls1!=NULL){
999 if(ls1->obj->parent==obj){
1000 ls1->obj->parent=NULL;
1001 }
1002 if(ls1->obj->dest==obj){
1003 ls1->obj->dest=NULL;
1004 }
1005 ls1=ls1->next;
1006 }
1007
1008 DelAllOrder(freels->obj);
1009
1010 free(freels->obj);
1011 freels->obj=NULL;
1012 MemUsed(MADD,-sizeof(Object));
1013 free(freels);
1014
1015 MemUsed(MADD,-sizeof(struct ObjList));
1016 freels=NULL;
1017 lhobjs->n--;
1018 } /* if(ls->obj==obj2remove) */
1019 else{
1020 fprintf(stderr,"ERROR en removeobj()\n");
1021 exit(-1);
1022 }
1023
1024
1025 return;
1026 }
1027
CountPlayerShipObjs(struct HeadObjList * lh,int player,int * cont)1028 int CountPlayerShipObjs(struct HeadObjList *lh,int player,int *cont){
1029 /*
1030 Count the number of ship of the player player
1031 return this values in the vector cont.
1032 return the total number of ships.
1033 */
1034
1035 struct ObjList *ls;
1036 int n=0;
1037
1038 cont[0]=cont[1]=cont[2]=0;
1039 ls=lh->list;
1040 while(ls!=NULL){
1041 if(ls->obj->player!=player){ls=ls->next;continue;}
1042 if(ls->obj->type!=SHIP){ls=ls->next;continue;}
1043 switch(ls->obj->subtype){
1044 case TOWER:
1045 cont[0]++;
1046 break;
1047 case EXPLORER:
1048 cont[1]++;
1049 break;
1050 case FIGHTER:
1051 cont[2]++;
1052 break;
1053 default:
1054 n++;
1055 break;
1056 }
1057 ls=ls->next;
1058 }
1059
1060 return(n+cont[0]+cont[1]+cont[2]);
1061 }
1062
1063
NewPlanet(void)1064 struct Planet *NewPlanet(void){
1065 /*
1066 Create the normailized surface of a planet
1067 returns a pointer to the planet surface
1068 */
1069 int x,y;
1070 int ix,iy;
1071 int x0,l;
1072 struct Planet *planet;
1073 Segment *s;
1074 /* int width=GameParametres(GET,GWIDTH,0); */
1075 int width=LXFACTOR;
1076 int factor=1;
1077 int sw=0;
1078
1079 planet=malloc(sizeof(struct Planet));
1080 MemUsed(MADD,+sizeof(struct Planet));
1081
1082 if(planet==NULL){
1083 fprintf(stderr,"ERROR in malloc NewPlanet()\n");
1084 exit(-1);
1085 }
1086
1087 planet->segment=malloc(sizeof(Segment));
1088 MemUsed(MADD,+sizeof(Segment));
1089 if(planet->segment==NULL){
1090 fprintf(stderr,"ERROR in malloc NewPlanet()2\n");
1091 exit(-1);
1092 }
1093
1094 /* first segment */
1095 planet->segment->next=NULL;
1096 s=planet->segment;
1097
1098 x=0;y=0;
1099 y=50*((float)rand()/RAND_MAX);
1100 s->x0=0;
1101 s->y0=50*((float)rand()/RAND_MAX);
1102 s->x1=20*((float)rand()/RAND_MAX);
1103 s->y1=s->y0+40*((float)rand()/RAND_MAX)-20;
1104 if(s->y1<0)s->y1=0;
1105 s->type=TERRAIN;
1106
1107 x=s->x1;
1108 y=s->y1;
1109
1110 /* size and position of landing zone */
1111 l=FACTORLANDZONESIZE*((float)rand()/RAND_MAX)+LANDZONEMINSIZE;
1112 if(l>width-x)l=width-x;
1113
1114 x0=(width-LANDZONEMINX-l)*((float)rand()/RAND_MAX)+LANDZONEMINX;
1115
1116 if(x0<x)x0=x;
1117
1118
1119 while(x < width){
1120
1121 ix =20*((float)rand()/RAND_MAX);
1122 iy =40*((float)rand()/RAND_MAX)-20;
1123
1124 if(x>width-100){
1125 if(y-planet->segment->y0 > 100)factor=2;
1126
1127 if(y>planet->segment->y0){
1128 iy =-factor*20*((float)rand()/RAND_MAX);
1129 }
1130 else{
1131 iy =20*((float)rand()/RAND_MAX);
1132 }
1133 }
1134
1135 if(y+iy<5)continue;
1136 if(y+iy>MAXPLANETHEIGHT)continue;
1137
1138
1139 s->next=malloc(sizeof(Segment));
1140 MemUsed(MADD,+sizeof(Segment));
1141 if(s->next==NULL){
1142 fprintf(stderr,"ERROR in malloc NewPlanet()\n");
1143 exit(-1);
1144 }
1145
1146 s=s->next;
1147 s->next=NULL;
1148 if(x<x0){
1149 s->x0=x;
1150 s->y0=y;
1151 x+=ix;
1152 y+=iy;
1153 if(x>width)x=width;
1154
1155 s->x1=x;
1156 s->y1=y;
1157 s->type=TERRAIN;
1158 }
1159 else{
1160 s->x0=x;
1161 s->y0=y;
1162 x+=l;
1163 y+=0;
1164 if(x>width)x=width-2;
1165
1166 s->x1=x;
1167 s->y1=y;
1168 s->type=LANDZONE;
1169 sw++;
1170 x0=width;
1171 }
1172 }
1173
1174 /* last segment */
1175 s->next=malloc(sizeof(Segment));
1176 MemUsed(MADD,+sizeof(Segment));
1177 if(s->next==NULL){
1178 fprintf(stderr,"ERROR in malloc NewPlanet()2\n");
1179 exit(-1);
1180 }
1181 s->next->x0=s->x1;
1182 s->next->y0=s->y1;
1183 s->next->x1=width;
1184 s->next->y1=planet->segment->y0;
1185 s->next->type=TERRAIN;
1186 s=s->next;
1187 s->next=NULL;
1188
1189 if(sw==0){
1190 fprintf(stderr,"ERROR in NewPlanet(): planet too small\n");
1191 fprintf(stderr,"\tincrease window geometry\n");
1192 exit(-1);
1193 }
1194 return planet;
1195 }
1196
1197
GetLandedZone(Segment * segment,struct Planet * planet)1198 int GetLandedZone(Segment *segment,struct Planet *planet){
1199
1200 Segment *s;
1201
1202 if(planet==NULL){
1203 return(0);
1204 }
1205
1206 s=planet->segment;
1207 while(s!=NULL){
1208 switch(s->type){
1209 case LANDZONE:
1210 segment->x0=s->x0;
1211 segment->x1=s->x1;
1212 segment->y0=s->y0;
1213 segment->y1=s->y1;
1214 segment->type=s->type;
1215 return(0);
1216 break;
1217 default:
1218 break;
1219 }
1220 s=s->next;
1221 }
1222 return(1);
1223 }
1224
1225
GetSegment(Segment * segment,struct Planet * planet,float x,float y)1226 int GetSegment(Segment *segment,struct Planet *planet,float x,float y){
1227 /*
1228 returns the segment below the ship
1229 */
1230 Segment *s;
1231
1232 if(planet==NULL)return(0);
1233 /* if(obj->habitat!=H_PLANET)return(0); */
1234
1235 s=planet->segment;
1236
1237 while(s!=NULL){
1238
1239 if(x > s->x0 && x < s->x1){
1240 segment->x0=s->x0;
1241 segment->x1=s->x1;
1242 segment->y0=s->y0;
1243 segment->y1=s->y1;
1244 segment->type=s->type;
1245 return(0);
1246 }
1247 s=s->next;
1248 }
1249 return(1);
1250 }
1251
1252
1253
Explosion(struct HeadObjList * lh,Object * cv,Object * obj,int type)1254 void Explosion(struct HeadObjList *lh,Object *cv,Object *obj,int type){
1255 /*
1256 Create explosion objects.
1257 */
1258 int i;
1259 float v,vx,vy;
1260 float a;
1261 Object *nobj;
1262 int nexplosion=16;
1263 int swexplosion=0;
1264
1265 struct timeval time;
1266 static int n=0;
1267 static struct timeval time0;
1268
1269
1270 /* max 500 explosion dots by second */
1271 gettimeofday(&time,NULL);
1272 if(time.tv_sec-time0.tv_sec>1 ){
1273 n=0;
1274 }
1275 if(n==0){
1276 time0=time;
1277 }
1278 if(n>500)return;
1279
1280
1281 if(obj==NULL)return;
1282 if(cv==NULL)return;
1283
1284 /* only there are an explosion if you can see it. */
1285
1286 if(cv->habitat==obj->habitat){
1287 if(cv->habitat==H_PLANET){
1288 if(cv->in==obj->in)swexplosion++;
1289 }
1290 else{
1291 /* check if are close */
1292 if( (cv->x-obj->x)*(cv->x-obj->x)+(cv->y-obj->y)*(cv->y-obj->y)<4000000)
1293 swexplosion++;
1294 }
1295 }
1296 if(!swexplosion)return;
1297
1298
1299 switch (type){
1300 case 0: /* ship destroyed */
1301 nexplosion=(64*obj->mass)/100;
1302 n+=nexplosion;
1303 for(i=0;i<nexplosion;i++){ /* 16 */
1304 a=2.*PI*(Random(-1));
1305 v=1.0*VELMAX*(Random(-1));
1306 vx=v*cos(a) + obj->vx;
1307 vy=v*sin(a) + obj->vy;
1308 nobj=NewObj(PROJECTILE,EXPLOSION,obj->x,obj->y,vx,vy,
1309 CANNON0,ENGINE0,obj->player,obj,obj->in);
1310 if(nobj!=NULL){
1311 nobj->life*=(.25+Random(-1));
1312 Add2ObjList(lh,nobj);
1313 nobj->parent=NULL;
1314 }
1315 }
1316 break;
1317 case 1: /* ship hitted */
1318 n+=4;
1319 for(i=0;i<4;i++){
1320 a=2.*PI*(Random(-1));
1321 v=0.5*VELMAX*(Random(-1));
1322 vx=v*cos(a) + obj->vx;
1323 vy=v*sin(a) + obj->vy;
1324 nobj=NewObj(PROJECTILE,EXPLOSION,obj->x,obj->y,vx,vy,
1325 CANNON0,ENGINE0,obj->player,obj,obj->in);
1326 if(nobj!=NULL){
1327 Add2ObjList(lh,nobj);
1328 nobj->parent=NULL;
1329 }
1330 }
1331 break;
1332 default:
1333 fprintf(stderr,"Error Explosion(): type %d not implemented\n",type);
1334 exit(-1);
1335 break;
1336 }
1337 }
1338
1339
CountPlayerPlanets(struct HeadObjList * lh,struct Player * player,int * cont)1340 int CountPlayerPlanets(struct HeadObjList *lh,struct Player *player,int *cont){
1341 /*
1342 version 0.1
1343 Count the known planets of the player player.
1344 return the status of the known planets in the vector cont
1345 returns the total number of known planets.
1346 */
1347 struct ObjList *ls;
1348
1349 cont[0]=cont[1]=cont[2]=0;
1350 ls=lh->list;
1351 while(ls!=NULL){
1352 if(ls->obj->type==PLANET){
1353 if(IsInIntList((player->kplanets),ls->obj->id)){
1354
1355 if(ls->obj->player==0)cont[0]++; /* INEXPLORE */
1356 else{
1357 if(ls->obj->player==player->id)cont[1]++; /* ALLY */
1358 else{
1359 cont[2]++; /* ENEMY */
1360 }
1361 }
1362 }
1363 }
1364 ls=ls->next;
1365 }
1366 return (cont[0]+cont[1]+cont[2]);
1367 }
1368
1369
CountPlanets(struct HeadObjList * lh,int type)1370 int CountPlanets(struct HeadObjList *lh,int type){
1371 /*
1372 Count the planets of the list
1373 */
1374 struct ObjList *ls;
1375 int n=0;
1376
1377 printf("CountPlanets():\n");
1378
1379 ls=lh->list;
1380 while(ls!=NULL){
1381 printf("%p\n",(void *)ls);
1382 n++;
1383 ls=ls->next;
1384 }
1385 return n;
1386 }
1387
CountShipsInPlanet(struct HeadObjList * lh,int objid,int player,int type,int stype,int max)1388 int CountShipsInPlanet(struct HeadObjList *lh,int objid,int player,int type,int stype,int max){
1389 /*
1390 Count the number of ships inside the object objid of type and subtype
1391 of the player player.
1392 if type or subtype are equal to -1 count all.
1393 if lh is NULL use the all objects list.
1394 Returns the number of ships.
1395 */
1396
1397 struct ObjList *ls;
1398 int n=0;
1399
1400 if(lh!=NULL){
1401 ls=lh->list;
1402 }
1403 else{
1404 ls=listheadobjs.list;
1405 }
1406 while(ls!=NULL){
1407 if(type!=-1){
1408 if(ls->obj->state<=0){ls=ls->next;continue;}
1409 if(ls->obj->type!=type){ls=ls->next;continue;}
1410 if(stype!=-1){
1411 if(ls->obj->subtype!=stype){ls=ls->next;continue;}
1412 }
1413 }
1414 if(ls->obj->player!=player){ls=ls->next;continue;}
1415
1416 if(ls->obj->in!=NULL){
1417 if(ls->obj->in->id==objid)n++;
1418 if(max>0 && n>=max)return(max);
1419 }
1420 else{ /* Count ships in space */
1421 if(objid==0)n++;
1422 if(max>0 && n>=max)return(max);
1423 }
1424
1425 ls=ls->next;
1426 }
1427 return(n);
1428 }
1429
1430
CountShips(struct HeadObjList * lh,int * planet,int * ships)1431 int CountShips(struct HeadObjList *lh,int *planet,int *ships){
1432 /*
1433 Count the number of ships in planet
1434 Returns the number of ships.
1435 */
1436
1437 struct ObjList *ls;
1438 int n=0;
1439 int i;
1440
1441 for(i=0;i<MAXNUMPLANETS+1;i++){
1442 planet[i]=0;
1443 }
1444 for(i=0;i<SHIP_S_MAX+1;i++){
1445 ships[i]=0;
1446 }
1447 ls=lh->list;
1448 while(ls!=NULL){
1449
1450 if(ls->obj->type!=SHIP){ls=ls->next;continue;}
1451 if(ls->obj->state<=0){ls=ls->next;continue;}
1452 if(ls->obj->habitat==H_PLANET){
1453 if(ls->obj->in!=NULL){
1454 if(ls->obj->in->id < 1 ||ls->obj->in->id > MAXNUMPLANETS){
1455 fprintf(stderr,"ERROR: wrong planet id in CountShips(): %d\n",
1456 ls->obj->in->id);
1457 ls=ls->next;continue;
1458 }
1459 }
1460 else{
1461 fprintf(stderr,"ERROR in CountShips(): in NULL id: %d\n",ls->obj->id);
1462 ls=ls->next;continue;
1463 }
1464 planet[ls->obj->in->id - 1]++;
1465 }
1466 else{
1467 planet[MAXNUMPLANETS]++;
1468 }
1469 ships[ls->obj->subtype]++;
1470 n++;
1471 ls=ls->next;
1472 }
1473 return(n);
1474 }
1475
1476
CopyObject(Object * nobj,Object * obj)1477 int CopyObject(Object *nobj,Object *obj){
1478
1479 memcpy(nobj,obj,sizeof(Object));
1480 return (sizeof(Object));
1481 }
1482
SelectObj(struct HeadObjList * lh,int id)1483 Object *SelectObj(struct HeadObjList *lh,int id){
1484 /*
1485 returns:
1486 a pointer to the Object with the id id,
1487 NULL if not exist.
1488 */
1489 struct ObjList *ls;
1490
1491 if(id==0)return(NULL);
1492
1493 ls=lh->list;
1494 while(ls!=NULL){
1495 if(ls->obj->id==id)
1496 return(ls->obj);
1497 ls=ls->next;
1498 }
1499 return(NULL);
1500 }
1501
1502
SelectpObj(struct HeadObjList * lh,int pid,int player)1503 Object *SelectpObj(struct HeadObjList *lh,int pid,int player){
1504 /*
1505 returns:
1506 a pointer to the Object with the id id,
1507 NULL if not exist.
1508 */
1509 struct ObjList *ls;
1510
1511 if(pid==0)return(NULL);
1512
1513 ls=lh->list;
1514 while(ls!=NULL){
1515 if(ls->obj->type!=PLANET && ls->obj->player != player){ls=ls->next;continue;}
1516 if(ls->obj->pid==pid){
1517 return(ls->obj);
1518 }
1519 ls=ls->next;
1520 }
1521 return(NULL);
1522 }
1523
1524
SelectObjInObj(struct HeadObjList * lh,int id,int player)1525 Object *SelectObjInObj(struct HeadObjList *lh,int id,int player){
1526 /*
1527 returns:
1528 a pointer to the first Object which is inside of id
1529 NULL if not exist.
1530 */
1531 struct ObjList *ls;
1532
1533 if(id==0)return(NULL);
1534
1535
1536 ls=lh->list;
1537 while(ls!=NULL){
1538 if(ls->obj->in == NULL){ls=ls->next;continue;}
1539 if(ls->obj->in->id != id){ls=ls->next;continue;}
1540 if(ls->obj->id == id){ls=ls->next;continue;}
1541 if(ls->obj->player != player){ls=ls->next;continue;}
1542 if(ls->obj->type!=SHIP){ls=ls->next;continue;}
1543
1544 if(ls->obj->state >= 0){
1545 return(ls->obj);
1546 }
1547 ls=ls->next;
1548 }
1549 return(NULL);
1550 }
1551
SelectpObjInObj(struct HeadObjList * lh,int pid,int player)1552 Object *SelectpObjInObj(struct HeadObjList *lh,int pid,int player){
1553 /*
1554 returns:
1555 a pointer to the first Object which is inside of id
1556 NULL if not exist.
1557 */
1558 struct ObjList *ls;
1559
1560 if(pid==0)return(NULL);
1561 if(pid<=GameParametres(GET,GNPLANETS,0))return(SelectObjInObj(lh,pid,player));
1562
1563 ls=lh->list;
1564 while(ls!=NULL){
1565 if(ls->obj->in == NULL){ls=ls->next;continue;}
1566 if(ls->obj->in->pid != pid){ls=ls->next;continue;}
1567 if(ls->obj->pid == pid){ls=ls->next;continue;}
1568 if(ls->obj->player != player){ls=ls->next;continue;}
1569 if(ls->obj->type!=SHIP){ls=ls->next;continue;}
1570
1571 if(ls->obj->state >= 0){
1572 return(ls->obj);
1573 }
1574 ls=ls->next;
1575 }
1576 return(NULL);
1577 }
1578
1579
SelectOneShip(struct HeadObjList * lh,Space reg,Object * cv,int ctrl)1580 Object *SelectOneShip(struct HeadObjList *lh,Space reg,Object *cv,int ctrl){
1581 /*
1582 select the nearest obj to mouse pointer
1583 return the obj selected
1584 */
1585
1586 struct ObjList *ls;
1587 Rectangle rect;
1588 float x,y;
1589 int sw1=0; /* first selected */
1590 Object *ret;
1591 float d2,d2min=10000;
1592
1593 if(lh==NULL)return(NULL);
1594
1595 ret=NULL;
1596
1597 rect.x=reg.rect.x;
1598 rect.y=reg.rect.y;
1599
1600 ls=lh->list;
1601 while(ls!=NULL){
1602 if(ls->obj->player!=actual_player){ls=ls->next;continue;}
1603 if(ls->obj->type!=SHIP){ls=ls->next;continue;}
1604 if(ls->obj->habitat!=H_SPACE && ls->obj->habitat!=H_PLANET){ls=ls->next;continue;}
1605
1606
1607 if(ctrl==FALSE)ls->obj->selected=FALSE;
1608
1609 if(reg.habitat>0){ /* select a region inside a planet */
1610 if(ls->obj->habitat==H_SPACE){ls=ls->next;continue;}
1611 if(reg.habitat!=ls->obj->in->id){ls=ls->next;continue;}
1612 d2=(rect.x-ls->obj->x)*(rect.x-ls->obj->x)+(rect.y-ls->obj->y)*(rect.y-ls->obj->y);
1613 }
1614 else{ /* select a region in map view */
1615 if(ls->obj->habitat==H_PLANET){
1616 x=ls->obj->in->x;
1617 y=ls->obj->in->y;
1618 }
1619 else{
1620 x=ls->obj->x;
1621 y=ls->obj->y;
1622 }
1623 d2=(rect.x-x)*(rect.x-x)+(rect.y-y)*(rect.y-y);
1624 }
1625
1626 if(d2<d2min||sw1==0){
1627 ret=ls->obj;
1628 d2min=d2;
1629 sw1++;
1630 }
1631 ls=ls->next;
1632 }
1633 return(ret);
1634 }
1635
1636
IsInRegion(Object * obj,Space region)1637 int IsInRegion(Object *obj,Space region){
1638 Point a,b;
1639 Rectangle rect;
1640 rect.x=region.rect.x;
1641 rect.y=region.rect.y;
1642 rect.width=region.rect.width;
1643 rect.height=region.rect.height;
1644
1645 if(region.rect.width<0){
1646 rect.x+=region.rect.width;
1647 rect.width*=-1;
1648 }
1649
1650 if(region.rect.height<0){
1651 rect.y+=region.rect.height;
1652 rect.height*=-1;
1653 }
1654 if(region.habitat>0){ /* select a region inside a planet */
1655 a.x=rect.x;
1656 a.y=rect.y-rect.height;
1657 b.x=rect.x+rect.width;
1658 b.y=rect.y;
1659 }
1660 else{ /* select a region in map view */
1661 a.x=rect.x;
1662 a.y=rect.y;
1663 b.x=rect.x+rect.width;
1664 b.y=rect.y+rect.height;
1665 }
1666 if(obj->x < a.x || obj->x > b.x || obj->y < a.y || obj->y > b.y ){
1667 /*reset */
1668
1669 return(TRUE);
1670 }
1671 return(FALSE);
1672
1673 }
1674
1675
Distance2NearestShip(struct HeadObjList * lh,int player,int x,int y)1676 float Distance2NearestShip(struct HeadObjList *lh,int player,int x,int y){
1677 /*
1678
1679 Return the distance2 of the nearest SHIP to the point x,y. x,y
1680 are space coordinates, no planet. The nearest obj can be in free
1681 space or inside a planet. In this last case the coordinates are
1682 the planet ones.
1683 if player = -1 match all players
1684 */
1685
1686 float d2;
1687 struct ObjList *ls;
1688 float rx,ry,r2;
1689 float x1,y1;
1690 Object *obj=NULL;
1691 int sw=0;
1692
1693 /* if(!PLANETSKNOWN) */
1694 /* if(IsInIntList((players[player].kplanets),ls->obj->id)==0)break; */
1695
1696 d2=-1;
1697
1698 ls=lh->list;
1699 while(ls!=NULL){
1700 if(ls->obj->type!=SHIP){ls=ls->next;continue;}
1701 if(ls->obj->player!=player && player !=-1){ls=ls->next;continue;}
1702
1703 obj=ls->obj;
1704
1705 switch(obj->habitat){
1706 case H_PLANET:
1707 x1=obj->in->x;
1708 y1=obj->in->y;
1709 break;
1710 case H_SPACE:
1711 x1=obj->x;
1712 y1=obj->y;
1713 break;
1714 default:
1715 ls=ls->next;continue;
1716 break;
1717 }
1718
1719 rx=x - x1;
1720 ry=y - y1;
1721 r2=rx*rx+ry*ry;
1722
1723 if(sw==0|| r2<d2){
1724 d2=r2;
1725 sw++;
1726 }
1727 ls=ls->next;
1728 }
1729 return(d2);
1730 }
1731
1732
Distance2NearestShipLessThan(struct HeadObjList * lh,int player,int x,int y,float dmin2)1733 float Distance2NearestShipLessThan(struct HeadObjList *lh,int player,int x,int y,float dmin2){
1734 /*
1735
1736 returns 1 if the distance2 to nearest SHIP to the point x,y is less than dmin2.
1737 returns 0 if is greater.
1738 x,y are space coordinates, no planet. The nearest obj can be in free
1739 space or inside a planet. In this last case the coordinates are
1740 the planet ones.
1741 if player = -1 match all players
1742
1743 */
1744
1745 float d2;
1746 struct ObjList *ls;
1747 float rx,ry,r2;
1748 float x1,y1;
1749 Object *obj=NULL;
1750 int sw=0;
1751
1752 /* if(!PLANETSKNOWN) */
1753 /* if(IsInIntList((players[player].kplanets),ls->obj->id)==0)break; */
1754
1755 d2=-1;
1756
1757 ls=lh->list;
1758 while(ls!=NULL){
1759 if(ls->obj->type!=SHIP){ls=ls->next;continue;}
1760 if(ls->obj->player!=player && player !=-1){ls=ls->next;continue;}
1761
1762 obj=ls->obj;
1763
1764 switch(obj->habitat){
1765 case H_PLANET:
1766 x1=obj->in->x;
1767 y1=obj->in->y;
1768 break;
1769 case H_SPACE:
1770 x1=obj->x;
1771 y1=obj->y;
1772 break;
1773 default:
1774 ls=ls->next;continue;
1775 break;
1776 }
1777
1778 rx=x - x1;
1779 ry=y - y1;
1780 r2=rx*rx+ry*ry;
1781
1782 if(sw==0|| r2<d2){
1783 d2=r2;
1784 if(d2<dmin2)return(1);
1785 sw++;
1786 }
1787 ls=ls->next;
1788 }
1789 return(0);
1790 }
1791
ObjNearThan(struct HeadObjList * lh,int player,int x,int y,float d2)1792 Object *ObjNearThan(struct HeadObjList *lh,int player,int x,int y,float d2){
1793 /*
1794 returns:
1795 the nearest obj planet id of first planet closer than dmin2.
1796 0 if there are no planets at that distance.
1797 */
1798
1799 struct ObjList *ls;
1800 float rx,ry;
1801 float dmin2;
1802 Object *obj=NULL;
1803 Object *retobj=NULL;
1804 struct Player *players;
1805
1806 players=GetPlayers();
1807 dmin2=d2;
1808
1809 ls=lh->list;
1810 while(ls!=NULL){
1811 if(ls->obj->player!=player && ls->obj->type!=PLANET){ls=ls->next;continue;}
1812 if(ls->obj->habitat!=H_SPACE){ls=ls->next;continue;}
1813 if(ls->obj->type!=PLANET && ls->obj->type!=SHIP){ls=ls->next;continue;}
1814
1815 if(ls->obj->type==PLANET){
1816 if(!PLANETSKNOWN){
1817 if(IsInIntList((players[player].kplanets),ls->obj->id)==0){
1818 ls=ls->next;continue;
1819 }
1820 }
1821 }
1822 obj=ls->obj;
1823
1824 rx=x - obj->x;
1825 ry=y - obj->y;
1826
1827 if(rx*rx+ry*ry<dmin2){
1828 dmin2=rx*rx+ry*ry;
1829 retobj=obj;
1830 }
1831 ls=ls->next;
1832 }
1833 return(retobj);
1834 }
1835
1836
1837
NearestObj(struct HeadObjList * lh,Object * obj,int type,int stype,int pstate,float * d2)1838 Object *NearestObj(struct HeadObjList *lh,Object *obj,int type,int stype,int pstate,float *d2){
1839 /*
1840 Return a pointer to the nearest object to obj in state pstate.
1841 pstate can be own, ally, enemy or inexplore.
1842 in d2 returns the distance^2.
1843 */
1844
1845 struct ObjList *ls;
1846 float rx,ry,r2;
1847 float x0,y0,x1,y1;
1848 float r2min;
1849 int player;
1850 Object *robj=NULL;
1851 Object *obj2=NULL;
1852 int pheight2=0;
1853 int swp=0;
1854 int sw=0;
1855 struct Player *players;
1856
1857 players=GetPlayers();
1858
1859
1860 /* if(!PLANETSKNOWN) */
1861 /* if(IsInIntList((players[player].kplanets),ls->obj->id)==0)break; */
1862
1863 *d2=-1;
1864 if(obj==NULL)return(NULL);
1865
1866 player=obj->player;
1867 r2min=-1;
1868 obj->dest_r2=-1;
1869
1870 if(obj->habitat==H_PLANET){
1871 pheight2=(0.7)*GameParametres(GET,GHEIGHT,0);
1872 pheight2*=pheight2;
1873 }
1874
1875 ls=lh->list;
1876 while(ls!=NULL){
1877 obj2=ls->obj;
1878 if(obj2->type!=type){ls=ls->next;continue;}
1879
1880 if(stype!=SHIP0){
1881 if(obj2->subtype!=stype){ls=ls->next;continue;}
1882 }
1883
1884 switch(obj2->type){
1885 case SHIP:
1886 if(obj2->ttl<MINTTL){ls=ls->next;continue;}
1887 if(obj2->state<=0){
1888 ls=ls->next;continue;
1889 }
1890
1891 if(obj2->subtype==PILOT){
1892 ls=ls->next;continue; /* ignoring pilots */
1893 if(obj2->mode==LANDED){ls=ls->next;continue;}
1894 if(obj2->habitat==H_SHIP){ls=ls->next;continue;}
1895 }
1896 break;
1897 case PLANET:
1898 if(IsInIntList((players[obj->player].kplanets),obj2->id)==0){
1899 ls=ls->next;continue;
1900 }
1901 break;
1902 default:
1903 break;
1904 }
1905
1906 sw=0;
1907 if(pstate & PENEMY){
1908 if((players[obj2->player].team!=players[player].team) && obj2->player!=0) {sw=1;}
1909 }
1910 if(pstate & PINEXPLORE){
1911 if(obj2->player==0){sw=1;}
1912 }
1913 if(pstate & PALLY){
1914 if(players[obj2->player].team==players[player].team){sw=1;}
1915 }
1916 if(!sw){ls=ls->next;continue;}
1917
1918 if(obj2==obj){ls=ls->next;continue;}
1919
1920 if(obj2->habitat==H_PLANET){
1921 if(obj->habitat!=H_PLANET){ls=ls->next;continue;}
1922
1923 if(obj->habitat==H_PLANET){
1924 if(obj->in!=obj2->in){ls=ls->next;continue;}
1925 }
1926 }
1927
1928 x0=obj->x;
1929 y0=obj->y;
1930
1931 swp=0;
1932 if(obj->habitat==H_PLANET && obj2->habitat!=H_PLANET){
1933 x0=obj->in->x;
1934 y0=obj->in->y;
1935 swp=1;
1936 }
1937 x1=obj2->x;
1938 y1=obj2->y;
1939
1940 rx=x0 - x1;
1941 ry=y0 - y1;
1942 r2=rx*rx+ry*ry;
1943 if(swp)r2+=pheight2;
1944
1945 if(robj==NULL || r2<r2min){
1946 r2min=r2;
1947 *d2=r2;
1948 obj->dest_r2=r2;
1949 robj=obj2;
1950 }
1951 ls=ls->next;
1952 }
1953 obj->dest=robj;
1954 return(robj);
1955 }
1956
1957
NearestObjAll(struct HeadObjList * lhc,Object * obj,struct NearObject * objs)1958 void NearestObjAll(struct HeadObjList *lhc,Object *obj,struct NearObject *objs){
1959 /*
1960 version 03
1961 look for closer object to obj in the list lhc.
1962
1963 In vector objs save the next information, (in order):
1964 the nearest enemy ship or ASTEROID
1965 the nearest known enemy planet
1966 the nearest known inexplore planet
1967 the nearest known ally planet
1968 */
1969
1970 struct ObjList *ls;
1971 Object *obj2;
1972 int i,j;
1973 float rx,ry,r2;
1974 float x0,y0;
1975 int player;
1976 float radar2;
1977 int nlist;
1978 int pheight2=0;
1979 int swp=0;
1980 struct Player *players;
1981
1982
1983
1984 for(i=0;i<4;i++){
1985 objs[i].obj=NULL;
1986 objs[i].d2=-1;
1987 }
1988
1989 if(obj==NULL)return;
1990 if(obj->habitat!=H_SPACE && obj->habitat!=H_PLANET)return;
1991
1992 players=GetPlayers();
1993 player=obj->player;
1994 radar2=obj->radar*obj->radar;
1995
1996 if(obj->habitat==H_PLANET){
1997 pheight2=(0.7)*GameParametres(GET,GHEIGHT,0);
1998 pheight2*=pheight2;
1999 }
2000
2001 /* among free space and planets */
2002 nlist=3;
2003 if(obj->habitat==H_SPACE){
2004 nlist=2;
2005 }
2006 for(j=0;j<nlist;j++){
2007 switch(j){
2008 case 0:
2009 ls=listheadkplanets[obj->player].list;
2010 break;
2011 case 1:
2012 ls=lhc[0].list;
2013 break;
2014 default:
2015 ls=lhc[(obj->in->id)].list;
2016 break;
2017 }
2018
2019 while(ls!=NULL){
2020 obj2=ls->obj;
2021
2022 switch(obj2->type){
2023 case SHIP:
2024 case ASTEROID:
2025 if(obj2->player==obj->player){
2026 ls=ls->next;continue;
2027 }
2028 if(obj2->ttl<MINTTL){ls=ls->next;continue;}
2029
2030 if(obj2->state<=0){
2031 ls=ls->next;continue;
2032 }
2033
2034 if(obj->habitat==H_PLANET && obj2->habitat==H_PLANET){
2035 if(obj->in != obj2->in){
2036 /* unupdated list */
2037
2038 ls=ls->next;continue;
2039 }
2040 }
2041 /* ignore pilots */
2042 if(obj2->type==SHIP && obj2->subtype==PILOT){ls=ls->next;continue;}
2043
2044 break;
2045 case PLANET:
2046 if(j!=0){ls=ls->next;continue;}
2047 break;
2048 default:
2049 ls=ls->next;continue;
2050 }
2051 swp=0;
2052 if(obj->habitat==H_PLANET && obj2->habitat!=H_PLANET){
2053 x0=obj->in->x;
2054 y0=obj->in->y;
2055 swp=1;
2056 }
2057 else{
2058 x0=obj->x;
2059 y0=obj->y;
2060 }
2061
2062 rx=x0 - obj2->x;
2063 ry=y0 - obj2->y;
2064 r2=rx*rx+ry*ry;
2065 if(swp)r2+=pheight2;
2066
2067 switch(obj2->type){
2068 case SHIP:
2069 if(r2>radar2){ls=ls->next;continue;}
2070 case ASTEROID:
2071 if(r2>25*radar2){ls=ls->next;continue;}
2072
2073 if( players[obj2->player].team!=players[player].team ){ /* Enemy Ship */
2074 if(objs[0].obj==NULL){ /* first element */
2075 objs[0].obj=obj2;
2076 objs[0].d2=r2;
2077 }
2078 else{
2079 if(r2<objs[0].d2){
2080 objs[0].obj=obj2;
2081 objs[0].d2=r2;
2082 }
2083 }
2084 }
2085 break;
2086
2087 case PLANET:
2088 if(obj2->player!=0 && (players[obj2->player].team != players[player].team )){ /* Enemy Planet */
2089 if(objs[1].obj==NULL){
2090 objs[1].obj=obj2;
2091 objs[1].d2=r2;
2092 }
2093 else{
2094 if(r2<objs[1].d2){
2095 objs[1].obj=obj2;
2096 objs[1].d2=r2;
2097 }
2098 }
2099 break;
2100 }
2101
2102 if((obj2->player==0) ){ /* Inexplore Planet */
2103 if(objs[2].obj==NULL){
2104 objs[2].obj=obj2;
2105 objs[2].d2=r2;
2106 }
2107 else{
2108 if(r2<objs[2].d2){
2109 objs[2].obj=obj2;
2110 objs[2].d2=r2;
2111 }
2112 }
2113 break;
2114 }
2115
2116 if((players[obj2->player].team==players[player].team) ){ /* Ally Planet */
2117 if(objs[3].obj==NULL){
2118 objs[3].obj=obj2;
2119 objs[3].d2=r2;
2120 }
2121 else{
2122 if(r2<objs[3].d2){
2123 objs[3].obj=obj2;
2124 objs[3].d2=r2;
2125 }
2126 }
2127 break;
2128 }
2129 break;
2130 default:
2131 fprintf(stderr,"ERROR in NearestObjAll\n");
2132 exit(-1);
2133 break;
2134 }
2135 ls=ls->next;
2136 }
2137 }
2138 return;
2139 }
2140
2141
DestroyAllObj(struct HeadObjList * lh)2142 void DestroyAllObj(struct HeadObjList *lh){
2143 struct ObjList *ls,*ls0;
2144
2145 ls=lh->list;
2146
2147 while(ls!=NULL){
2148 DestroyObj(ls->obj);
2149 ls->obj=NULL;
2150 ls0=ls;
2151 ls=ls->next;
2152 free(ls0);
2153 ls0=NULL;
2154 MemUsed(MADD,-sizeof(struct ObjList));
2155 lh->n--;
2156 }
2157 }
2158
2159
DestroyAllPlayerObjs(struct HeadObjList * lh,int player)2160 void DestroyAllPlayerObjs(struct HeadObjList *lh,int player){
2161 struct ObjList *ls;
2162
2163 ls=lh->list;
2164
2165 while(ls!=NULL){
2166 if(ls->obj->player!=player){ls=ls->next;continue;}
2167 if(ls->obj->type==SHIP){
2168 ls->obj->state=0;
2169 }
2170 ls=ls->next;
2171 }
2172 }
2173
2174
DestroyObj(Object * obj)2175 void DestroyObj(Object *obj){
2176 /*
2177 Use only when load a game
2178 */
2179 if(obj==NULL)return;
2180 DelAllOrder(obj);
2181 CargoDestroy(obj);
2182 if(obj->type==PLANET){
2183 DestroyPlanet(obj->planet);
2184 }
2185 if(obj->cdata!=NULL){ /* HERE COMPUTER, only ships */
2186 if(obj->type!=SHIP){ /* checking */
2187 fprintf(stderr,"ERROR DestroyObj(): obj is not a SHIP\n");
2188 exit(-1);
2189 }
2190 free(obj->cdata);
2191 obj->cdata=NULL;
2192 MemUsed(MADD,-sizeof(Data));
2193
2194 }
2195 free(obj);
2196 obj=NULL;
2197 MemUsed(MADD,-sizeof(Object));
2198 }
2199
DestroyPlanet(struct Planet * planet)2200 void DestroyPlanet(struct Planet *planet){
2201 Segment *s,*s0;
2202
2203 s=planet->segment;
2204 while(s!=NULL){
2205 s0=s;
2206 s=s->next;
2207 free(s0);
2208 s0=NULL;
2209 MemUsed(MADD,-sizeof(Segment));
2210
2211 }
2212 free(planet);
2213 planet=NULL;
2214 MemUsed(MADD,-sizeof(struct Planet));
2215
2216 }
2217
CopyPlanet2Buf(struct Planet * planet,char * buf)2218 int CopyPlanet2Buf(struct Planet *planet,char *buf){
2219 struct Planet *planet2;
2220 Segment *s,*s2;
2221 int offset=0;
2222
2223 planet2=(struct Planet *)buf;
2224
2225 planet2->x=planet->x;
2226 planet2->y=planet->y;
2227 planet2->r=planet->r;
2228 planet2->gold=planet->gold;
2229 planet2->segment=planet->segment;
2230 offset=sizeof(struct Planet);
2231
2232 s=planet->segment;
2233
2234 s2=(Segment *)(buf+offset);
2235
2236
2237 while(s!=NULL){
2238
2239 s2->x0=s->x0;
2240 s2->y0=s->y0;
2241 s2->x1=s->x1;
2242 s2->y1=s->y1;
2243 s2->type=s->type;
2244 s2->next=s->next;
2245
2246 offset+=sizeof(Segment);
2247 s2++;
2248 s=s->next;
2249 }
2250 return(offset);
2251 }
2252
2253
CopyBuf2Planet(char * buf,struct Planet * planet)2254 int CopyBuf2Planet(char *buf,struct Planet *planet){
2255 struct Planet *planet2;
2256 Segment *s,*s2;
2257 int offset=0;
2258
2259 planet=malloc(sizeof(struct Planet));
2260 MemUsed(MADD,+sizeof(struct Planet));
2261 if(planet==NULL){
2262 fprintf(stderr,"ERROR in malloc CopyBuf2Planet()\n");
2263 exit(-1);
2264 }
2265
2266 planet2=(struct Planet *)buf;
2267
2268 planet->x=planet2->x;
2269 planet->y=planet2->y;
2270 planet->r=planet2->r;
2271 planet->gold=planet2->gold;
2272 planet->segment=NULL;
2273
2274 offset=sizeof(struct Planet);
2275
2276 s=malloc(sizeof(Segment));
2277 MemUsed(MADD,+sizeof(Segment));
2278 if(s==NULL){
2279 fprintf(stderr,"ERROR in malloc CopyBuf2Planet()2\n");
2280 exit(-1);
2281 }
2282 s->next=NULL;
2283 planet->segment=s;
2284
2285 s2=(Segment *)(buf+offset);
2286
2287 s->x0=s2->x0;
2288 s->y0=s2->y0;
2289 s->x1=s2->x1;
2290 s->y1=s2->y1;
2291 s->type=s2->type;
2292 s->next=NULL;
2293
2294
2295 while(s2->next!=NULL){
2296 s->next=malloc(sizeof(Segment));
2297 MemUsed(MADD,+sizeof(Segment));
2298 if(s->next==NULL){
2299 fprintf(stderr,"ERROR in malloc CopyBuf2Planet()2\n");
2300 exit(-1);
2301 }
2302 s->next->next=NULL;
2303 s=s->next;
2304 s2++;
2305 offset+=sizeof(Segment);
2306
2307 s->x0=s2->x0;
2308 s->y0=s2->y0;
2309 s->x1=s2->x1;
2310 s->y1=s2->y1;
2311 s->type=s2->type;
2312 }
2313 return(0);
2314 }
2315
2316
UpdateSectors(struct HeadObjList lh)2317 int UpdateSectors(struct HeadObjList lh){
2318 /*
2319 add the actual sector to his own player list
2320
2321 */
2322
2323 struct ObjList *ls;
2324 int n=0;
2325 int i,j,k;
2326 int i2,k2,is;
2327 int time;
2328 int proc=0;
2329 float maxx,maxy;
2330 struct Player *players;
2331
2332 players=GetPlayers();
2333 proc=GetProc();
2334 time=GetTime();
2335
2336 maxx=0.55*GameParametres(GET,GULX,0);
2337 maxy=0.55*GameParametres(GET,GULY,0);
2338
2339 ls=lh.list;
2340
2341 while(ls!=NULL){
2342 if((ls->obj->id + time)%20){ls=ls->next;continue;}
2343 if(proc==players[ls->obj->player].proc){
2344 if(ls->obj->type==SHIP && ls->obj->habitat==H_SPACE){
2345
2346 if(ls->obj->x>maxx || ls->obj->x<-maxx || ls->obj->y>maxy || ls->obj->y<-maxy){
2347 ls=ls->next;continue;
2348 }
2349
2350 switch(ls->obj->subtype){
2351 case EXPLORER:
2352 case SATELLITE:
2353 case QUEEN:
2354 k=ls->obj->radar/SECTORSIZE;
2355 k2=k*k;
2356 for(i=-k;i<k+1;i++){
2357 i2=i*i;
2358 is=i*SECTORSIZE;
2359 for(j=-k;j<k+1;j++){
2360 if(i2+j*j<=k2){
2361 Add2IntIList(&(players[ls->obj->player].ksectors),
2362 Quadrant(ls->obj->x+is,ls->obj->y+j*SECTORSIZE));
2363 }
2364 }
2365 }
2366 break;
2367 default:
2368 Add2IntIList(&(players[ls->obj->player].ksectors),
2369 Quadrant(ls->obj->x,ls->obj->y));
2370 break;
2371 }
2372
2373 n++;
2374 }
2375 }
2376 ls=ls->next;
2377 }
2378 return n;
2379 }
2380
Add2TextMessageList(struct TextMessageList * listhead,char * cad,int source,int dest,int mid,int time,int priority)2381 int Add2TextMessageList(struct TextMessageList *listhead,char *cad,
2382 int source,int dest,int mid,int time,int priority){
2383 /*
2384 version 02. April 2 2011
2385 add the integer id to the list by priority given by priority
2386 if is not already added.
2387 where:
2388 cad: the message.
2389 source: the object id
2390 dest: the destination player. -1 : for all players
2391 mid: is a message indentifier.
2392 time: the duration of the message in centiseconds.
2393 priority: priority.
2394 returns:
2395 0 if the message is added to the list
2396 1 if not, because is already added.
2397 */
2398 struct TextMessageList *list;
2399 struct TextMessageList *lh;
2400 int n=0;
2401
2402 /* Add text at the end of the list */
2403
2404 if(dest!=actual_player && dest!=-1){
2405 return(1);
2406 }
2407
2408 lh=listhead;
2409 while(lh->next!=NULL){
2410
2411 if(lh->next->info.source==source && lh->next->info.id==mid && lh->next->info.value==priority){ /* already added */
2412 return(1);
2413 }
2414
2415 if(lh->next->info.value<priority){ /* added before end */
2416 break;
2417 }
2418 n++;
2419 lh=lh->next;
2420 }
2421
2422 list=malloc(sizeof(struct TextMessageList));
2423 MemUsed(MADD,+sizeof(struct TextMessageList));
2424 if(list==NULL){
2425 fprintf(stderr,"ERROR in malloc Add2TextMessageList()\n");
2426 exit(-1);
2427 }
2428 list->info.source=source;
2429 list->info.dest=dest;
2430 list->info.id=mid;
2431 list->info.value=priority;
2432 list->info.time=GetTime();
2433 list->info.print=0;
2434 list->info.duration=time;
2435 strncpy(list->info.text,cad,MAXTEXTLEN);
2436
2437 if(lh->next==NULL){ /* is the lastest */
2438 list->next=NULL;
2439 lh->next=list;
2440 }
2441 else{
2442 list->next=lh->next->next;
2443 lh->next=list;
2444 }
2445 listhead->info.n++;
2446 /* gdk_beep(); */
2447 return (0);
2448 }
2449
2450
GetPrice(Object * obj,int stype,int eng,int weapon)2451 int GetPrice(Object *obj,int stype,int eng,int weapon){
2452 /*
2453 return:
2454 -1 if there are some error
2455 the price of the object obj
2456 if obj is NULL the price given for the other parametres.
2457 */
2458 static int ship_price[]={PRICESHIP0,PRICESHIP1,PRICESHIP2,PRICESHIP3,PRICESHIP4,PRICESHIP5,PRICESHIP6,PRICESHIP7,PRICESHIP8};
2459 static int engine_price[]={PRICEENGINE0,PRICEENGINE1,PRICEENGINE2,PRICEENGINE3,PRICEENGINE4,PRICEENGINE5};
2460 static int weapon_price[NUMWEAPONS]={PRICECANNON0,PRICECANNON1,PRICECANNON2,PRICECANNON3,PRICECANNON4,PRICECANNON5,PRICECANNON6,PRICECANNON7,PRICECANNON8,PRICECANNON9};
2461 int price=0;
2462 int level=0;
2463
2464
2465 if(obj!=NULL){
2466 if(obj->type!=SHIP){
2467 fprintf(stdout,"ERROR in GetPrice() obj type:%d\n",obj->type);
2468 return(-1);
2469 }
2470
2471 stype=obj->subtype;
2472 eng=obj->engine.type;
2473 weapon=obj->weapon0.type;
2474 level=obj->level;
2475
2476 if(obj->type==SHIP && obj->subtype==PILOT){
2477 /* TODO show this only in human game */
2478 eng=ENGINE0;
2479 weapon=CANNON0;
2480 }
2481 }
2482
2483 if(stype<SHIP0 || stype>SHIP_S_MAX){
2484 fprintf(stderr,"ERROR in GetPrice() stype id:%d\n",stype);
2485 return(-1);
2486 }
2487 if(eng<ENGINE0 || eng>ENGINEMAX){
2488 fprintf(stderr,"ERROR in GetPrice() engine id:%d\n",eng);
2489 return(-1);
2490 }
2491 if(weapon<CANNON0 || weapon>CANNONMAX){
2492 fprintf(stderr,"ERROR in GetPrice() weapon id:%d\n",weapon);
2493 return(-1);
2494 }
2495
2496 price+=ship_price[stype];
2497 price+=engine_price[eng];
2498 price+=weapon_price[weapon];
2499 price*=(level+1);
2500
2501 return(price);
2502 }
2503
BuyShip(struct Player * player,Object * obj,int stype)2504 int BuyShip(struct Player *player,Object *obj,int stype){
2505 /*
2506 buy and create an SHIP of subtype stype
2507 returns:
2508 an error code:
2509 0 ok
2510 1 obj is null
2511 2 obj is not landed
2512 3 player in a enemy planet
2513 4 Code error, must not happen
2514 5 Error in GetPrice()
2515 6 Not enough gold.
2516 7 Not enought room
2517 */
2518
2519 Object *obj_b;
2520 Segment *s;
2521 float r;
2522 int price=0;
2523 float shield;
2524
2525 if(obj==NULL)return(SZ_OBJNULL);
2526 if(obj->mode!=LANDED)return(SZ_OBJNOTLANDED);
2527 if(obj->player!=obj->in->player && stype==TOWER){
2528 printf("Warning: Buyship() player: %d planet: %d. Not owned.\n",player->id,obj->in->player);
2529 return(SZ_NOTOWNPLANET);
2530 }
2531
2532 if(obj->type==SHIP && obj->subtype==PILOT && stype!=FIGHTER){ /* pilot buy a ship */
2533 printf("A pilot only can buy FIGHTERS\n");
2534 return(SZ_NOTALLOWED);
2535 }
2536
2537 switch(stype){
2538 case EXPLORER:
2539 price=GetPrice(NULL,EXPLORER,ENGINE3,CANNON3);
2540 break;
2541 case FIGHTER:
2542 price=GetPrice(NULL,FIGHTER,ENGINE4,CANNON4);
2543 break;
2544 case TOWER:
2545 price=GetPrice(NULL,TOWER,ENGINE1,CANNON4);
2546 break;
2547 case FREIGHTER:
2548 price=GetPrice(NULL,FREIGHTER,ENGINE6,CANNON0);
2549 break;
2550 case SATELLITE:
2551 if(obj->cargo.mass + MASSSATELLITE > obj->cargo.capacity){
2552 return(SZ_NOTENOUGHROOM);
2553 }
2554 price=GetPrice(NULL,SATELLITE,ENGINE1,CANNON3);
2555 break;
2556 case GOODS:
2557 if(obj->cargo.mass + MASSGOODS > obj->cargo.capacity){
2558 return(SZ_NOTENOUGHROOM);
2559 }
2560 price=GetPrice(NULL,GOODS,ENGINE0,CANNON0);
2561 break;
2562
2563 default:
2564 fprintf(stderr,"WARNING in Buyship() ship stype %d not implemented\n",stype);
2565 return(SZ_NOTIMPLEMENTED);
2566 break;
2567
2568 }
2569 if(price<0)return(SZ_UNKNOWNERROR);
2570 if(player->gold < price)return(SZ_NOTENOUGHGOLD);
2571
2572
2573 if(obj->type==SHIP && obj->subtype==PILOT){ /* pilot buy a ship */
2574 shield=obj->shield;
2575 ShipProperties(obj,stype,obj->in);
2576 obj->shield=shield;
2577 obj->cost*=pow(2,obj->level);
2578 obj->subtype=stype;
2579 obj->a=PI/2;
2580 obj->ai=1;
2581 obj->durable=FALSE;
2582 obj->mode=LANDED;
2583 obj->habitat=H_PLANET;
2584 /* obj->selected=FALSE; */
2585 if(obj->in->type!=PLANET){
2586 fprintf(stderr,"ERROR BuyShip() pilot buying\n");
2587 }
2588
2589 if(GameParametres(GET,GNET,0)==TRUE){
2590 SetModified(obj,SENDOBJALL);
2591 }
2592 player->gold -=price;
2593 return(SZ_OK);
2594 }
2595
2596 s=LandZone(obj->in->planet);
2597 if(s==NULL){
2598 fprintf(stderr,"ERROR BuyShip(): Segment==NULL\n");
2599 exit(-1);
2600 }
2601
2602 switch(stype){
2603 case EXPLORER:
2604 obj_b=NewObj(SHIP,EXPLORER,
2605 obj->x,s->y0,
2606 0,0,
2607 CANNON3,ENGINE3,obj->player,NULL,obj->in);
2608 break;
2609 case FIGHTER:
2610 obj_b=NewObj(SHIP,FIGHTER,
2611 obj->x,s->y0,
2612 0,0,
2613 CANNON4,ENGINE4,obj->player,NULL,obj->in);
2614 break;
2615 case TOWER:
2616 obj_b=NewObj(SHIP,TOWER,
2617 obj->x,s->y0,
2618 0,0,
2619 CANNON4,ENGINE1,obj->player,NULL,obj->in);
2620 break;
2621 case FREIGHTER:
2622 obj_b=NewObj(SHIP,FREIGHTER,
2623 obj->x,s->y0,
2624 0,0,
2625 CANNON0,ENGINE6,obj->player,NULL,obj->in);
2626 obj_b->oriid=obj->in->id;
2627 break;
2628
2629 case SATELLITE:
2630 obj_b=NULL;
2631
2632 obj_b=NewObj(SHIP,SATELLITE,
2633 obj->x,s->y0,
2634 0,0,
2635 CANNON3,ENGINE1,obj->player,NULL,obj->in);
2636
2637 break;
2638 case GOODS:
2639 obj_b=NULL;
2640
2641 obj_b=NewObj(SHIP,GOODS,
2642 obj->x,s->y0,
2643 0,0,
2644 CANNON0,ENGINE0,obj->player,NULL,obj->in);
2645
2646 break;
2647
2648 default:
2649 obj_b=NULL;
2650 fprintf(stderr,"ERROR in Buyship() ship stype %d not implemented\n",stype);
2651 return(SZ_NOTIMPLEMENTED);
2652 break;
2653
2654 }
2655
2656
2657 if(obj_b!=NULL){
2658 player->gold -=price;
2659 player->goldships+=price;
2660 /* obj_b->y+=obj_b->radio+1; */
2661 r=s->x1-s->x0-2*obj_b->radio;
2662
2663 obj_b->x=s->x0+obj_b->radio+r*(Random(-1));
2664 obj_b->y+=obj_b->radio+1;
2665 obj_b->player=obj->player;
2666 obj_b->a=PI/2;
2667 obj_b->habitat=obj->habitat;
2668 obj_b->planet=NULL;
2669 obj_b->gas=obj_b->gas_max*(.5+.5*(Random(-1)));
2670 obj_b->mode=LANDED;
2671
2672 if(stype==SATELLITE){
2673 if(CargoAdd(obj,obj_b)){
2674 obj_b->weapon->n=obj_b->weapon->max_n;
2675 obj_b->gas=obj_b->gas_max;
2676 obj_b->state=100;
2677 obj_b->habitat=H_SHIP;
2678 obj_b->in=obj;
2679 }
2680 }
2681 if(stype==GOODS){
2682 if(CargoAdd(obj,obj_b)){
2683 obj_b->state=100;
2684 obj_b->habitat=H_SHIP;
2685 obj_b->in=obj;
2686 }
2687 }
2688
2689 player->nbuildships++;
2690
2691 Add2ObjList(&listheadobjs,obj_b);
2692 if(GameParametres(GET,GNET,0)==TRUE){
2693 SetModified(obj,SENDOBJNEW);/* HERE obj or obj_b???*/
2694 }
2695 }
2696 else{
2697 fprintf(stderr,"ERROR in BuyShip()\n");
2698 }
2699 return(SZ_OK);
2700 }
2701
2702
2703
NextCv(struct HeadObjList * lh,Object * cv0,int pid)2704 Object *NextCv(struct HeadObjList *lh,Object *cv0,int pid){
2705 /*
2706 returns:
2707 if cv0 is NULL a pointer to the first ship
2708 if cv0 != NULL a pointer to the next ship in the list
2709
2710 */
2711
2712 struct ObjList *ls;
2713 Object *obj1=NULL;
2714 int sw1=0;
2715 int swcv=0;
2716
2717 ls=lh->list;
2718 if(ls==NULL){
2719 printf("There are no ship selected!!\n");
2720 return(NULL);
2721 }
2722
2723 while(ls!=NULL){ /* find the actual cv */
2724 if(ls->obj->player!=pid){ls=ls->next;continue;}
2725 if(ls->obj->type!=SHIP){ls=ls->next;continue;}
2726 if(ls->obj->subtype==PILOT && ls->obj->habitat==H_SHIP){ls=ls->next;continue;}
2727
2728 if(!sw1){
2729 if(cv0==NULL){
2730 return(ls->obj); /* first found */
2731 }
2732 obj1=ls->obj;
2733 sw1=1;
2734 }
2735 if(!swcv && cv0!=NULL){
2736 if(ls->obj==cv0)
2737 swcv=1;
2738 }
2739 if(swcv && ls->obj!=cv0){
2740 return(ls->obj); /* first after cv */
2741 }
2742
2743 ls=ls->next;
2744 }
2745 return(obj1);
2746 }
2747
PrevCv(struct HeadObjList * lh,Object * cv0,int pid)2748 Object *PrevCv(struct HeadObjList *lh,Object *cv0,int pid){
2749 /*
2750 returns:
2751 if cv0 is NULL a pointer to the first ship
2752 if cv0 != NULL a pointer to the previous ship in the list
2753
2754 */
2755
2756 struct ObjList *ls;
2757 Object *obj,*pobj;
2758
2759 obj=pobj=NULL;
2760
2761 ls=lh->list;
2762 if(ls==NULL){
2763 printf("There are no ship selected!!\n");
2764 return(NULL);
2765 }
2766
2767 while(ls!=NULL){
2768 obj=ls->obj;
2769 if(obj->player==pid && obj->type==SHIP){
2770 if(obj->subtype==PILOT && obj->habitat==H_SHIP){ls=ls->next;continue;}
2771 if(cv0==NULL)return(obj); /* first found */
2772 else{
2773 if(obj!=cv0)pobj=obj;
2774 if(obj==cv0){
2775 if(pobj!=NULL)return(pobj);
2776 }
2777 }
2778 }
2779 ls=ls->next;
2780 }
2781 if(pobj==NULL && cv0!=NULL)return(cv0);
2782 return(pobj);
2783 }
2784
2785
FirstShip(struct HeadObjList * lh,Object * cv0,int pid)2786 Object *FirstShip(struct HeadObjList *lh,Object *cv0,int pid){
2787 /*
2788 returns:
2789 a pointer to the first ship in free space.
2790 if not, the actual selected cv0.
2791 */
2792
2793 struct ObjList *ls;
2794
2795 ls=lh->list;
2796 if(ls==NULL){
2797 printf("There are no ship selected!!\n");
2798 return(NULL);
2799 }
2800
2801 while(ls!=NULL){
2802 if(ls->obj->player!=pid){ls=ls->next;continue;}
2803 if(ls->obj->type!=SHIP){ls=ls->next;continue;}
2804 if(ls->obj->subtype==PILOT && ls->obj->habitat==H_SHIP){ls=ls->next;continue;}
2805
2806 if(ls->obj->habitat==H_SPACE){
2807 return(ls->obj); /* first found */
2808 }
2809
2810
2811 ls=ls->next;
2812 }
2813
2814 return(cv0);
2815 }
2816
PrevPlanetCv(struct HeadObjList * lh,Object * cv0,int playerid)2817 Object *PrevPlanetCv(struct HeadObjList *lh,Object *cv0,int playerid){
2818 /*
2819 version 01
2820 returns:
2821 if cv0 is NULL a pointer to the first planet
2822 if cv0 != NULL a pointer to the previous planet in the list
2823 */
2824
2825 struct ObjList *ls;
2826 Object *pobj=NULL;
2827 int pplanet=-1;
2828 int planet0=-1;
2829 int planet;
2830
2831 ls=lh->list;
2832 if(ls==NULL){
2833 printf("There are no ship selected!!\n");
2834 return(NULL);
2835 }
2836 if(cv0!=NULL){
2837 planet0=cv0->habitat==H_PLANET ? cv0->in->id : 0;
2838 }
2839
2840 while(ls!=NULL){
2841
2842 if(ls->obj->player!=playerid){ls=ls->next;continue;}
2843 if(ls->obj->type!=SHIP){ls=ls->next;continue;}
2844 if(ls->obj->subtype==PILOT && ls->obj->habitat==H_SHIP){ls=ls->next;continue;}
2845 if(cv0==NULL)return(ls->obj);
2846
2847 planet=ls->obj->habitat==H_PLANET ? ls->obj->in->id : 0;
2848 if(planet==planet0){
2849 if(pobj!=NULL)return(pobj);
2850 else{
2851 ls=ls->next;continue;
2852 }
2853 }
2854 else{
2855 if(pplanet!=planet){
2856 pobj=ls->obj;
2857 pplanet=planet;
2858 }
2859 }
2860 ls=ls->next;
2861 }
2862 if(pobj==NULL && cv0!=NULL)return(cv0);
2863 return(pobj);
2864 }
2865
2866
NextPlanetCv(struct HeadObjList * lh,Object * cv0,int playerid)2867 Object *NextPlanetCv(struct HeadObjList *lh,Object *cv0,int playerid){
2868 /*
2869 returns:
2870 if cv0 is NULL a pointer to the first ship
2871 if cv0 != NULL a pointer to the first ship in next planet in the list
2872 */
2873
2874 struct ObjList *ls;
2875 Object *obj1;
2876 int sw1=0;
2877 int swcv=0;
2878 int planet0=0;
2879
2880
2881 ls=lh->list;
2882 if(ls==NULL){
2883 printf("There are no ship selected!!\n");
2884 return(NULL);
2885 }
2886
2887 obj1=NULL;
2888 if(cv0!=NULL){
2889 if(cv0->habitat==H_PLANET){
2890 planet0=cv0->in->id;
2891 }
2892 }
2893
2894 while(ls!=NULL){ /* find the actual cv */
2895 if(ls->obj->player==playerid && ls->obj->type==SHIP){
2896 if(ls->obj->subtype==PILOT && ls->obj->habitat==H_SHIP){ls=ls->next;continue;}
2897 if(!sw1){
2898 if((cv0==NULL || planet0==0) && ls->obj->habitat==H_PLANET){
2899 return(ls->obj); /* first found */
2900 }
2901 obj1=ls->obj;
2902 sw1=1;
2903 }
2904 if(!swcv && cv0!=NULL){
2905 if(ls->obj==cv0)
2906 swcv=1;
2907 }
2908 if(swcv && ls->obj!=cv0 && ls->obj->habitat==H_PLANET){
2909 if(planet0==0){
2910 return(ls->obj); /* first after cv */
2911 }
2912 else{
2913 if(planet0!=ls->obj->in->id){
2914 return(ls->obj);
2915 }
2916 }
2917 }
2918 }
2919 ls=ls->next;
2920 }
2921 return(obj1);
2922 }
2923
2924
CountObjList(struct HeadObjList * hlist)2925 int CountObjList(struct HeadObjList *hlist){
2926 /*
2927 returns:
2928 the number of item of the list hlist.
2929 */
2930 struct ObjList *ls;
2931 int n=0;
2932
2933 if(hlist==NULL)return(0);
2934 ls=hlist->list;
2935 while(ls!=NULL){
2936 n++;
2937 ls=ls->next;
2938 }
2939 return n;
2940 }
2941
2942
DestroyObjList(struct HeadObjList * hl)2943 int DestroyObjList(struct HeadObjList *hl){
2944 /*
2945 free memory for the list hl.
2946 */
2947 struct ObjList *ls0;
2948 int n=0;
2949 long memused=0;
2950
2951 if(hl==NULL)return(0);
2952
2953 while(hl->list!=NULL){
2954 ls0=hl->list;
2955 hl->list=hl->list->next;
2956 ls0->obj=NULL;
2957 ls0->next=NULL;
2958 free(ls0);
2959 ls0=NULL;
2960 memused-=sizeof(struct ObjList);
2961 hl->n--;
2962 n++;
2963 }
2964 MemUsed(MADD,memused);
2965
2966 if(hl->list!=NULL){
2967 fprintf(stderr,"ERROR 1 in DestroyObjList()\n");
2968 exit(-1);
2969 }
2970 if(hl->n!=0){
2971 fprintf(stderr,"ERROR 2 in DestroyObjList() n:%d del:%d\n",hl->n,n);
2972 hl->n=0;
2973 hl->list=NULL;
2974 /* exit(-1); */
2975 }
2976 return(n);
2977 }
2978
PrintObjList(struct HeadObjList * hl)2979 int PrintObjList(struct HeadObjList *hl){
2980 /*
2981 print some info of the list hl
2982 DEBUG only
2983 */
2984 if(hl==NULL)return(0);
2985 printf("List: ");
2986 while(hl->list!=NULL){
2987 printf("%d ",hl->list->obj->id);
2988 hl->list=hl->list->next;
2989 }
2990 printf("\n");
2991 return(0);
2992 }
2993
2994
IsInObjList(struct HeadObjList * lhobjs,Object * obj)2995 int IsInObjList(struct HeadObjList *lhobjs,Object *obj){
2996
2997 /*
2998 NOTUSED
2999 Look for obj in the list lhobjs
3000 returns:
3001 0 if obj is not in the list
3002 1 if is in the list
3003 */
3004
3005 struct ObjList *ls;
3006 if(lhobjs==NULL)return(-1);
3007 if(obj==NULL)return(0);
3008
3009 ls=lhobjs->list;
3010 while(ls!=NULL){
3011 if(ls->obj==obj)return(1);
3012 ls=ls->next;
3013 }
3014 return(0);
3015 }
3016
KillAllObjs(struct HeadObjList * lheadobjs)3017 void KillAllObjs(struct HeadObjList *lheadobjs){
3018 /*
3019 Kill all objects setting their state and life to zero.
3020 */
3021 struct ObjList *ls;
3022
3023 if(lheadobjs==NULL)return;
3024 ls=lheadobjs->list;
3025
3026 while(ls!=NULL){
3027 ls->obj->life=0;
3028 ls->obj->state=0;
3029 ls->obj->sw=0;
3030 ls=ls->next;
3031 }
3032 }
3033
3034
CreatePlayerList(struct HeadObjList hlist1,struct HeadObjList * hlist2,int player)3035 int CreatePlayerList(struct HeadObjList hlist1,struct HeadObjList *hlist2,int player){
3036 /*
3037 version 04
3038 Create a list in hlist2 only with ships an planets
3039 that belongs to player player from the list hlist1.
3040 return:
3041 the number of elements of the list.
3042 */
3043
3044 struct ObjList *ls0,*ls1,*ls2;
3045 Object *objin;
3046 int id1,id2;
3047 int n=0;
3048 long memused=0;
3049 struct Player *players;
3050
3051 players=GetPlayers();
3052
3053 if(hlist2->list!=NULL){
3054 fprintf(stderr,"WARNING CPL not NULL %p %d\n",(void *)hlist2->list,hlist2->n);
3055 }
3056
3057 hlist2->n=0;
3058 hlist2->list=NULL;
3059 ls0=ls1=ls2=NULL;
3060
3061 for(ls1=hlist1.list;ls1!=NULL;ls1=ls1->next){
3062
3063 switch(ls1->obj->type){
3064 case SHIP:
3065 if(ls1->obj->player!=player)continue;
3066 break;
3067 case PLANET:
3068 if(players[ls1->obj->player].team!=players[player].team)continue;
3069 break;
3070 default:
3071 continue;
3072 break;
3073 }
3074
3075 if(ls1->obj->subtype==SATELLITE)continue;
3076 if(ls1->obj->subtype==GOODS)continue;
3077 if(ls1->obj->state<=0)continue;
3078
3079
3080 id1=ls1->obj->id; /* id of the planet in which is contained, 0 for free space*/
3081 if(ls1->obj->type!=PLANET)id1=0;
3082
3083 /* HERENEW */
3084
3085 if(ls1->obj->in!=NULL){ /* not a planet */
3086 objin=ls1->obj->in;
3087 while(objin!=NULL){
3088 id1=objin->id;
3089 if(objin->type!=PLANET)id1=0;
3090 objin=objin->in;
3091 }
3092 }
3093
3094 ls0=malloc(sizeof(struct ObjList));
3095 memused+=sizeof(struct ObjList);
3096 /* MemUsed(MADD,+sizeof(struct ObjList)); */
3097 if(ls0==NULL){
3098 fprintf(stderr,"ERROR in malloc CreateList()\n");
3099 exit(-1);
3100 }
3101 ls0->obj=ls1->obj;
3102 ls0->next=NULL;
3103
3104
3105 if(hlist2->list==NULL){ /* first item */
3106 hlist2->list=ls0;
3107 hlist2->n++;
3108 n++;
3109 continue;
3110 }
3111
3112 id2=hlist2->list->obj->id;
3113 if(hlist2->list->obj->type!=PLANET)id2=0;
3114
3115 if(hlist2->list->obj->in!=NULL){
3116 objin=hlist2->list->obj->in;
3117 while(objin!=NULL){
3118 id2=objin->id;
3119 if(objin->type!=PLANET)id2=0;
3120 objin=objin->in;
3121 }
3122 }
3123
3124 if(id1 < id2 ){
3125 ls0->next=hlist2->list;
3126 hlist2->list=ls0;
3127 hlist2->n++;
3128 n++;
3129 continue;
3130 }
3131
3132 for(ls2=hlist2->list;ls2->next!=NULL;ls2=ls2->next){
3133
3134 id2=ls2->next->obj->id;
3135 if(ls2->next->obj->type!=PLANET)id2=0;
3136
3137 if(ls2->next->obj->in!=NULL){
3138 objin=ls2->next->obj->in;
3139 while(objin!=NULL){
3140 id2=objin->id;
3141 if(objin->type!=PLANET)id2=0;
3142 objin=objin->in;
3143 }
3144 }
3145
3146
3147 if(id1 < id2 )break;
3148 }
3149
3150 ls0->next=ls2->next;
3151 ls2->next=ls0;
3152
3153 hlist2->n++;
3154 n++;
3155 }
3156 MemUsed(MADD,memused);
3157 return(n) ;
3158 }
3159
3160
CreateContainerLists(struct HeadObjList * lh,struct HeadObjList * hcontainer)3161 int CreateContainerLists(struct HeadObjList *lh,struct HeadObjList *hcontainer){
3162 /*
3163 Create a list with all the objects that can collide.
3164 Create a container list for every planet
3165 Add to hcontainer all the objects in each planet plus free space objects
3166 returns:
3167 0
3168 */
3169 struct ObjList *ls;
3170 Object *obj;
3171 int nplanets;
3172 int i,n;
3173 int proc;
3174 int value0;
3175 int gulx,guly;
3176 struct Player *players;
3177
3178 players=GetPlayers();
3179
3180 for(i=0;i<GameParametres(GET,GNPLANETS,0)+1;i++){
3181 if(hcontainer[i].list!=NULL){
3182 fprintf(stderr,"WARNING: CCL() not NULL\n");
3183 }
3184 hcontainer[i].n=0;
3185 }
3186
3187 nplanets=GameParametres(GET,GNPLANETS,0);
3188 gulx=GameParametres(GET,GULX,0);
3189 guly=GameParametres(GET,GULY,0);
3190
3191 proc=GetProc();
3192
3193 ls=lh->list;
3194 while(ls!=NULL){
3195
3196 if(ls->obj->state<=0 && proc==players[ls->obj->player].proc){
3197 ls=ls->next;continue;
3198 }
3199 /* objects than don't collide */
3200 switch(ls->obj->type){
3201 case PROJECTILE:
3202 if(ls->obj->subtype==EXPLOSION && ls->obj->habitat==H_SPACE){
3203 ls=ls->next;continue;
3204 }
3205 break;
3206 case TRACE:
3207 case TRACKPOINT:
3208 ls=ls->next;
3209 continue;
3210 break;
3211 case SHIP:
3212 if(ls->obj->subtype==PILOT && ls->obj->mode==LANDED){
3213 ls=ls->next;
3214 continue;
3215 }
3216 break;
3217 default:
3218 break;
3219 }
3220 /* --objects than don't collide */
3221
3222 switch(ls->obj->habitat){
3223 case H_SPACE:
3224 n=0;
3225 break;
3226 case H_PLANET:
3227 n=ls->obj->in->id;
3228 break;
3229 case H_SHIP:
3230 ls=ls->next;continue;
3231 break;
3232 default:
3233 n=0;
3234 break;
3235 }
3236
3237 /* check */
3238
3239 if(n<0||n>nplanets){
3240 fprintf(stderr,"ERROR 1 in CreateContainerlists()\n");
3241 fprintf(stderr,"\t DEBUG info: n: %d objid:%d type: %d stype: %d\n",n,ls->obj->id,ls->obj->type,ls->obj->subtype);
3242 n=0;
3243 }
3244
3245 obj=ls->obj;
3246
3247 /**** CELLON****/
3248 if(n==0){
3249 switch(obj->type){
3250 case PLANET:
3251 value0=1;
3252 break;
3253 case ASTEROID:
3254 value0=2;
3255 break;
3256 case SHIP:
3257 value0=1<<(players[obj->player].team+3);
3258 if(obj->subtype==PILOT)value0=4;
3259 break;
3260 case PROJECTILE:
3261 value0=1<<(players[obj->player].team+3);
3262 break;
3263 default:
3264 ls=ls->next;
3265 continue;
3266 break;
3267 }
3268 if(ValueCell(cell,obj,gulx,guly)==value0){
3269 ls=ls->next;continue;
3270 }
3271 }
3272 /*****CELLON*****/
3273
3274 Add2ObjList(&hcontainer[n],ls->obj);
3275 ls=ls->next;
3276 }
3277 return(0);
3278 }
3279
3280
3281
CreatekplanetsLists(struct HeadObjList * lh,struct HeadObjList * hkplanets)3282 int CreatekplanetsLists(struct HeadObjList *lh,struct HeadObjList *hkplanets){
3283 /*
3284 Create a list with all the known planets.
3285 returns the number of objects of the list.
3286 */
3287 struct ObjList *ls;
3288 int gnplayers;
3289 int i;
3290 int n=0;
3291 int proc;
3292 struct Player *players;
3293
3294 players=GetPlayers();
3295 proc=GetProc();
3296 gnplayers=GameParametres(GET,GNPLAYERS,0);
3297
3298 for(i=0;i<gnplayers+1;i++){
3299 if(hkplanets[i].list!=NULL){
3300 fprintf(stderr,"WARNING: CkpL() not NULL\n");
3301 }
3302 hkplanets[i].n=0;
3303 }
3304
3305 ls=lh->list;
3306 while(ls!=NULL){
3307 if(ls->obj->type!=PLANET){ls=ls->next;continue;}
3308
3309 for(i=0;i<gnplayers+2;i++){
3310 if(proc==players[i].proc){
3311 if(IsInIntList(players[i].kplanets,ls->obj->id)){
3312 Add2ObjList(&hkplanets[i],ls->obj);
3313 n++;
3314 }
3315 }
3316 }
3317 ls=ls->next;
3318 }
3319 return(n);
3320 }
3321
3322
CreatePlanetList(struct HeadObjList lheadobjs,struct HeadObjList * lheadplanets)3323 int CreatePlanetList(struct HeadObjList lheadobjs,struct HeadObjList *lheadplanets){
3324 /*
3325 version 0.1
3326 Create a list of planets from the object list lheadobjs
3327 to obj. list lheadplanets.
3328 returns:
3329 the number of planets added to the list.
3330 */
3331
3332
3333 struct ObjList *ls,*ls0,*lsp;
3334 long memused=0;
3335
3336 if(lheadplanets->list!=NULL){
3337 DestroyObjList(lheadplanets);
3338 }
3339 lheadplanets->n=0;
3340
3341 ls=lheadobjs.list;
3342 ls0=NULL;
3343 lsp=NULL;
3344
3345 while(ls!=NULL){
3346 if(ls->obj->type==PLANET){
3347
3348 ls0=malloc(sizeof(struct ObjList));
3349 memused+=sizeof(struct ObjList);
3350
3351 if(ls0==NULL){
3352 fprintf(stderr,"ERROR in malloc() CreatePlanetList()\n");
3353 exit(-1);
3354 }
3355
3356 ls0->obj=ls->obj;
3357 ls0->next=NULL;
3358
3359 if(lheadplanets->n==0){
3360 lheadplanets->list=ls0;
3361 lsp=ls0;
3362 }
3363 else{
3364 lsp->next=ls0;
3365 lsp=ls0;
3366 }
3367 lheadplanets->n++;
3368 }
3369 ls=ls->next;
3370 }
3371 MemUsed(MADD,memused);
3372 return(lheadplanets->n);
3373 }
3374
3375
CreateNearObjsList(struct HeadObjList * lh,struct HeadObjList * lhn,int player)3376 void CreateNearObjsList(struct HeadObjList *lh,struct HeadObjList *lhn,int player){
3377 /*
3378 Create a list of enemy ships in radar range of the player player
3379 */
3380
3381 struct ObjList *ls1,*ls2;
3382 Object *obj1,*obj2;
3383
3384 float rx,ry,r2;
3385 int gnet,proc;
3386 struct Player *players;
3387
3388 players=GetPlayers();
3389 gnet=GameParametres(GET,GNET,0);
3390 proc=GetProc();
3391
3392 if(lhn->list!=NULL){
3393 fprintf(stderr,"WARNING: CNOL() not NULL\n");
3394 }
3395 lhn->n=0;
3396 ls1=lh->list;
3397 while(ls1!=NULL){
3398 obj1=ls1->obj;
3399
3400 /* obj1 is an enemy, a ship and in SPACE */
3401 if(players[obj1->player].team==players[player].team ||
3402 obj1->type!=SHIP ||
3403 obj1->habitat!=H_SPACE){
3404 ls1=ls1->next;continue;
3405 }
3406
3407 if(gnet==TRUE){
3408 if(proc!=players[obj1->player].proc){
3409 if(obj1->ttl<MINTTL){ls1=ls1->next;continue;}
3410 }
3411 }
3412
3413 ls2=lh->list;
3414 while(ls2 != NULL){
3415 /* obj2 is an ally */
3416 obj2=ls2->obj;
3417 if(obj2->player!=player){
3418 ls2=ls2->next;continue;
3419 }
3420 if(obj2->type!=SHIP){
3421 ls2=ls2->next;continue;
3422 }
3423
3424 switch(obj2->habitat){
3425 case H_SPACE:
3426 rx=obj2->x - obj1->x;
3427 ry=obj2->y - obj1->y;
3428 break;
3429 case H_PLANET:
3430 rx=obj2->in->x - obj1->x;
3431 ry=obj2->in->y - obj1->y;
3432 break;
3433 case H_SHIP:
3434 ls2=ls2->next;continue;
3435 break;
3436 default:
3437 fprintf(stderr,
3438 "ERROR in CreateNearObjsList() unknown habitat %d\n",
3439 obj2->habitat);
3440 exit(-1);
3441 break;
3442
3443 }
3444
3445 r2=rx*rx+ry*ry;
3446
3447 if(r2 < obj2->radar*obj2->radar){
3448 Add2ObjList(lhn,obj1);
3449 break;
3450 }
3451 ls2=ls2->next;
3452 }
3453 ls1=ls1->next;
3454 }
3455 }
3456
3457
3458
Experience(Object * obj,float pts)3459 void Experience(Object *obj,float pts){
3460 /*
3461 Increase ships level.
3462
3463 */
3464
3465 float mulshots;
3466 struct Player *players;
3467
3468 if(obj->state<=0){
3469 return;
3470 }
3471 if(obj->type!=SHIP)return;
3472 if(obj->subtype==PILOT)return;
3473
3474 players=GetPlayers();
3475
3476 players[obj->player].points+=pts;
3477 if(players[obj->player].points>=record){
3478 record=players[obj->player].points;
3479 }
3480
3481 obj->experience+=pts;
3482
3483
3484 while(obj->experience>=100*pow(2,obj->level)){
3485 obj->experience-=100*pow(2,obj->level);
3486 obj->level++;
3487 /* HERE obj->ttl=0; */
3488
3489 if(GameParametres(GET,GNET,0)==TRUE){
3490 /* if(GetProc()==players[obj->player].proc){ */
3491 SetModified(obj,SENDOBJALL);
3492 /* } */
3493 }
3494 obj->state=100;
3495 obj->gas=obj->gas_max;
3496 obj->engine.gascost-=.01;
3497 obj->engine.v_max++;
3498 obj->cost*=COSTINC*COSTFACTOR;
3499
3500 mulshots=1+1./(obj->level);
3501
3502 if(obj->weapon0.type!=CANNON0){
3503 obj->weapon0.max_n+=50;
3504 if(obj->weapon0.rate>9){
3505 obj->weapon0.rate--;
3506 }
3507 if(obj->weapon0.nshots<4){
3508 if(!(obj->level%2)){
3509 obj->weapon0.nshots++;
3510 }
3511 }
3512 obj->weapon0.projectile.damage*=1.+.2*DAMAGEFACTOR;
3513 }
3514
3515 if(obj->weapon1.type!=CANNON0){
3516 if(obj->weapon1.rate>9){
3517 obj->weapon1.rate--;
3518 }
3519 if(obj->weapon1.max_n<10){ /* max 11 missiles */
3520 obj->weapon1.max_n+=2;
3521 }
3522 obj->weapon1.projectile.damage*=1.+.2*DAMAGEFACTOR;
3523 }
3524
3525 if(obj->weapon2.type!=CANNON0){
3526 obj->weapon2.max_n*=mulshots;
3527 if(obj->weapon2.rate>9){
3528 obj->weapon2.rate--;
3529 }
3530 obj->weapon2.projectile.damage*=1.+.2*DAMAGEFACTOR;
3531 }
3532
3533 if(obj->engine.gascost<.01)obj->engine.gascost=.01;
3534 if(obj->engine.v_max>VELMAX)obj->engine.v_max=VELMAX;
3535
3536 obj->engine.v2_max=obj->engine.v_max*obj->engine.v_max;
3537
3538 switch(obj->subtype){
3539 case FIGHTER:
3540
3541 switch(obj->level){
3542 case 1:
3543 if(obj->weapon1.type==CANNON0){
3544 NewWeapon(&obj->weapon1,CANNON8);
3545 }
3546 break;
3547 case 2:
3548 if(obj->weapon2.type==CANNON0){
3549 NewWeapon(&obj->weapon2,CANNON9);
3550 }
3551 break;
3552 default:
3553 break;
3554 }
3555 obj->shield+=(.9-obj->shield)/3.;
3556 obj->engine.a_max*=1.10;
3557 break;
3558 case FREIGHTER:
3559 obj->cargo.capacity*=1.2;
3560 obj->engine.a_max*=1.15;
3561 obj->shield+=(.95-obj->shield)/2.;
3562 if(obj->shield>.95)obj->shield=.95;
3563 break;
3564 default:
3565 obj->shield+=(.9-obj->shield)/3.;
3566 if(obj->shield>.9)obj->shield=.9;
3567 break;
3568
3569
3570 }
3571
3572 }
3573 }
3574
PrintObj(Object * obj)3575 void PrintObj(Object *obj){
3576 printf("obj id:%d pid: %d type: %d stype: %d\n",
3577 obj->id,obj->pid,obj->type,obj->subtype);
3578 }
3579
Type(Object * obj)3580 char Type(Object *obj){
3581 /*
3582 returns:
3583 a char
3584 */
3585
3586 char mode=' ';
3587 if (obj==NULL)return(mode);
3588
3589 if(obj->type==SHIP){
3590 switch (obj->subtype){
3591 case FIGHTER:
3592 mode='F';
3593 break;
3594 case EXPLORER:
3595 mode='E';
3596 break;
3597 case TOWER:
3598 mode='T';
3599 break;
3600 case QUEEN:
3601 mode='Q';
3602 break;
3603 case FREIGHTER:
3604 mode='C';
3605 break;
3606 case PILOT:
3607 mode='A';
3608 break;
3609 case SATELLITE:
3610 mode='S';
3611 break;
3612 default:
3613 mode='O';
3614 break;
3615 }
3616 }
3617 return(mode);
3618 }
3619
TypeCad(Object * obj)3620 char *TypeCad(Object *obj){
3621 /*
3622 returns:
3623 a cad with the type of ship
3624 */
3625
3626 static char cad[16]="";
3627 if (obj==NULL)return(cad);
3628
3629 if(obj->type==SHIP){
3630 switch (obj->subtype){
3631 case FIGHTER:
3632 strcpy(cad,"FIGHTER");
3633 break;
3634 case EXPLORER:
3635 strcpy(cad,"EXPLORER");
3636 break;
3637 case TOWER:
3638 strcpy(cad,"TOWER");
3639 break;
3640 case QUEEN:
3641 strcpy(cad,"QUEEN");
3642 break;
3643 case PILOT:
3644 strcpy(cad,"PILOT");
3645 break;
3646 default:
3647 strcpy(cad,"");
3648 break;
3649 }
3650 }
3651 return(cad);
3652 }
3653
3654
MarkObjs(struct HeadObjList * lh,Space reg,Object * cv,int ctrl)3655 Object *MarkObjs(struct HeadObjList *lh,Space reg,Object *cv,int ctrl){
3656 /*
3657 Set the selected mark on in all ship inside the region reg.
3658 return a pointer to the first selected obj
3659 if cv is selected returns cv.
3660
3661 */
3662
3663 struct ObjList *ls;
3664 int n=0;
3665 Rectangle rect;
3666 int x,y;
3667 Point a,b;
3668 int sw1=0; /* first selected */
3669 Object *ret;
3670
3671 if(lh==NULL)return(NULL);
3672
3673 ret=NULL;
3674 rect.x=reg.rect.x;
3675 rect.y=reg.rect.y;
3676 rect.width=reg.rect.width;
3677 rect.height=reg.rect.height;
3678
3679 if(reg.rect.width<0){
3680 rect.x+=reg.rect.width;
3681 rect.width*=-1;
3682 }
3683
3684 if(reg.rect.height<0){
3685 rect.y+=reg.rect.height;
3686 rect.height*=-1;
3687 }
3688
3689 if(reg.habitat>0){ /* select a region inside a planet */
3690
3691 a.x=rect.x;
3692 a.y=rect.y-rect.height;
3693 b.x=rect.x+rect.width;
3694 b.y=rect.y;
3695
3696 }
3697 else{ /* select a region in map view */
3698
3699 a.x=rect.x;
3700 a.y=rect.y;
3701 b.x=rect.x+rect.width;
3702 b.y=rect.y+rect.height;
3703 }
3704
3705 ls=lh->list;
3706 while(ls!=NULL){
3707 if(ctrl==FALSE)ls->obj->selected=FALSE;
3708 if(ls->obj->player!=actual_player){ls=ls->next;continue;}
3709 if(ls->obj->type!=SHIP){ls=ls->next;continue;}
3710
3711 if(reg.habitat>0){ /* select a region inside a planet */
3712 if(ls->obj->habitat==H_SPACE){ls=ls->next;continue;}
3713 if(reg.habitat!=ls->obj->in->id){ls=ls->next;continue;}
3714
3715 if(ls->obj->x > a.x && ls->obj->x < b.x ){
3716 if(ls->obj->y+ls->obj->radio > a.y && ls->obj->y+ls->obj->radio < b.y ){
3717 if(sw1==0){
3718 if(ls->obj->habitat!=H_SHIP){
3719 ret=ls->obj;
3720 sw1++;
3721 }
3722 }
3723 ls->obj->selected=TRUE;
3724 n++;
3725 }
3726 }
3727 }
3728 else{ /* select a region in free space */
3729 if(ls->obj->habitat==H_PLANET){
3730 x=ls->obj->in->planet->x;
3731 y=ls->obj->in->planet->y;
3732 }
3733 else{
3734 x=ls->obj->x;
3735 y=ls->obj->y;
3736 }
3737
3738 if(x > a.x && x < b.x ){
3739 if(y > a.y && y < b.y ){
3740 if(sw1==0){
3741 if(ls->obj->habitat!=H_SHIP){
3742 ret=ls->obj;
3743 sw1++;
3744 }
3745 }
3746 ls->obj->selected=TRUE;
3747 n++;
3748 }
3749 }
3750 }
3751 ls=ls->next;
3752 }
3753 if(cv!=NULL){
3754 if(cv->selected==TRUE)return(cv);
3755 }
3756 return(ret);
3757 }
3758
3759
UnmarkObjs(struct HeadObjList * lh)3760 void UnmarkObjs(struct HeadObjList *lh){
3761 /*
3762 unmark all objects
3763 */
3764
3765 struct ObjList *ls;
3766
3767 if(lh==NULL)return;
3768 ls=lh->list;
3769 while(ls!=NULL){
3770 ls->obj->selected=FALSE;
3771 ls=ls->next;
3772 }
3773 return;
3774 }
3775
3776
PrintSelected(struct HeadObjList * lh)3777 int PrintSelected(struct HeadObjList *lh){
3778 /*
3779 printf the selected ships
3780 return the number of selected ships
3781 */
3782
3783 struct ObjList *ls;
3784 int n=0;
3785
3786 if(lh==NULL)return(0);
3787 ls=lh->list;
3788 while(ls!=NULL){
3789 if(ls->obj->selected==TRUE){
3790 printf("\t%c %d\n",Type(ls->obj),ls->obj->pid);
3791 n++;
3792 }
3793 ls=ls->next;
3794 }
3795 return n;
3796 }
3797
NearMaxLevelObj(Object * obj,struct HeadObjList * lh)3798 int NearMaxLevelObj(Object *obj,struct HeadObjList *lh){
3799 /*
3800 Not USED.
3801 return the max level of the objects in the list
3802 that belongs to same player that obj.
3803 pilots are not counted
3804 */
3805
3806 struct ObjList *ls;
3807 int maxlevel =0;
3808
3809
3810 if(lh==NULL)return(0);
3811 ls=lh->list;
3812 while(ls!=NULL){
3813 if(obj==ls->obj){ls=ls->next;continue;}
3814 if(ls->obj->player!=obj->player){ls=ls->next;continue;}
3815 if(ls->obj->type==SHIP && ls->obj->subtype==PILOT){ls=ls->next;continue;}
3816 if(ls->obj->level>maxlevel)maxlevel=ls->obj->level;
3817 ls=ls->next;
3818 } /* while(ls1!=NULL) */
3819 while(ls!=NULL);
3820 return(maxlevel);
3821 }
3822
IsPlanetEmpty(Object * planet,Object * obj)3823 int IsPlanetEmpty(Object *planet,Object *obj){
3824 /*
3825 don't count obj
3826 don't count pilots
3827 returns:
3828 0 if the planet is totally empty.
3829 1 if there are only allies landed.
3830 2 if there are enemy ships landed.
3831
3832 */
3833
3834 struct ObjList *ls;
3835 int gnet;
3836 int ret=0;
3837 struct Player *players;
3838
3839
3840 if(obj==NULL)return(-1);
3841 if(planet==NULL)return(-1);
3842 if(planet->player==0)return(0); /* planet never conquered */
3843
3844 players=GetPlayers();
3845 gnet=GameParametres(GET,GNET,0);
3846 ls=listheadobjs.list;
3847 while(ls!=NULL){
3848 if(ls->obj->in==planet){
3849 if(ls->obj->type!=SHIP){ls=ls->next;continue;}
3850 if(ls->obj->subtype==PILOT){ls=ls->next;continue;}
3851 if(ls->obj->mode!=LANDED){ls=ls->next;continue;}
3852 if(ls->obj==obj){ls=ls->next;continue;}
3853 if(gnet && ls->obj->ttl<MINTTL){ls=ls->next;continue;}
3854 if(ls->obj->state <= 0){ls=ls->next;continue;}
3855 if(players[ls->obj->player].team!=players[obj->player].team){
3856 return(2);
3857 }
3858 else{
3859 if(ls->obj->player!=obj->player)ret=1;
3860 }
3861 }
3862 ls=ls->next;
3863 }
3864 return(ret);
3865 }
3866
UpdateCell(struct HeadObjList * lh,int * cell)3867 int UpdateCell(struct HeadObjList *lh,int *cell){
3868 /*
3869 version 02 080411
3870 */
3871 struct ObjList *ls;
3872 Object *obj;
3873 int n=0;
3874 int dx,dy;
3875 int nx0,ny0,nx,ny;
3876 int nydx;
3877 int dx2,dy2;
3878 int i,j;
3879 int value;
3880 int gnet;
3881 struct Player *players;
3882
3883 players=GetPlayers();
3884 dx=GameParametres(GET,GULX,0)/DL;
3885 dy=GameParametres(GET,GULY,0)/DL;
3886 dx2=dx/2;
3887 dy2=dy/2;
3888 gnet=GameParametres(GET,GNET,0);
3889 ls=lh->list;
3890 while(ls!=NULL){
3891 if(ls->obj->habitat==H_PLANET){
3892 ls=ls->next;continue;
3893 }
3894
3895 obj=ls->obj;
3896 switch(obj->type){
3897 case SHIP:
3898 if(gnet==TRUE && obj->ttl<MINTTL){ls=ls->next;continue;}
3899 value=1<<(players[obj->player].team+3);
3900 if(obj->subtype==PILOT)value=4;
3901 break;
3902 case PROJECTILE:
3903 if(obj->subtype==EXPLOSION){
3904 ls=ls->next;continue;
3905 }
3906 value=1<<(players[obj->player].team+3);
3907 break;
3908 case PLANET:
3909 value=1;
3910 break;
3911 case ASTEROID:
3912 value=2;
3913 break;
3914 default:
3915 ls=ls->next;
3916 continue;
3917 break;
3918 }
3919
3920 nx0=(obj->x/DL+dx2);
3921 ny0=(obj->y/DL+dy2);
3922
3923 for(j=-1;j<=1;j++){
3924 ny=ny0+j;
3925 if(ny<0)ny=0;
3926 else{
3927 if(ny>=dy)ny=dy-1;
3928 }
3929 nydx=ny*dx;
3930
3931 for(i=-1;i<=1;i++){
3932 nx=nx0+i;
3933 if(nx<0)nx=0;
3934 else{
3935 if(nx>=dx)nx=dx-1;
3936 }
3937
3938 if((cell[nx+nydx]&value)==0){
3939 cell[nx+nydx]+=value;
3940 }
3941 }
3942 }
3943 n++;
3944 ls=ls->next;
3945 }
3946 return(n);
3947 }
3948
3949
ValueCell(int * cell,Object * obj,int gulx,int guly)3950 int ValueCell(int *cell,Object *obj,int gulx,int guly){
3951 /*
3952 The space is divided in cells usefull to create the lists of
3953 objects.
3954 HERECOM
3955 */
3956
3957 int x,y;
3958 int dx,dy;
3959 int nx,ny;
3960 int index;
3961
3962
3963 if(cell==NULL){
3964 fprintf(stderr,"ERROR: ValueCell(): cell NULL\n");
3965 return(0);
3966 }
3967 if(obj==NULL){
3968 fprintf(stderr,"ERROR: ValueCell(): obj NULL\n");
3969 exit(-1);
3970 return(0);
3971 }
3972
3973 dx=gulx/DL;
3974 dy=guly/DL;
3975
3976
3977 if(obj->habitat==H_PLANET){
3978 x=obj->in->planet->x;
3979 y=obj->in->planet->y;
3980 }
3981 else{
3982 x=obj->x;
3983 y=obj->y;
3984 }
3985
3986 nx=((int)x+(gulx)/2)/DL;
3987 ny=((int)y+(guly)/2)/DL;
3988 if(nx<0)nx=0;
3989 if(ny<0)ny=0;
3990 if(nx>=dx)nx=dx-1;
3991 if(ny>=dy)ny=dy-1;
3992
3993 index=nx+ny*dx;
3994
3995 if(index<0||index>=dx*dy){
3996 fprintf(stderr,"Error in ValueCell()\n");
3997 fprintf(stderr,"\tx:%f y:%f %d %d\n",obj->x,obj->y,nx,ny);
3998 exit(-1);
3999 return(0);
4000 }
4001 return(cell[index]);
4002 }
4003
4004
4005
ShipProperties(Object * obj,int stype,Object * in)4006 void ShipProperties(Object *obj,int stype,Object *in){
4007 /*
4008 TODO add only physical properties.
4009
4010 */
4011
4012 switch(stype){
4013 case EXPLORER: /* EXPLORER */
4014 obj->radar=2*RADAR_RANGE;
4015 obj->gas_max=1000;
4016 obj->gas=obj->gas_max;
4017 obj->shield=0;
4018 obj->state=90;
4019 obj->mass=MASSEXPLORER;
4020 obj->cargo.capacity=30;
4021 obj->radio=10;
4022 obj->ai=1;
4023 obj->damage=25;
4024 obj->cost=COSTEXPLORER*COSTFACTOR;
4025 break;
4026 case SHIP0: /* not used */
4027 /* HERE there are SHIP0 */
4028 case FIGHTER: /* FIGHTER */
4029 obj->gas_max=1000;
4030 obj->gas=obj->gas_max;
4031 obj->shield=0;
4032 obj->state=90;
4033 obj->mass=MASSFIGHTER;
4034
4035 if(stype==FIGHTER && obj->level>=MINLEVELPILOT) {
4036 obj->items=obj->items|ITSURVIVAL;
4037 }
4038 obj->cargo.capacity=30;
4039 obj->radio=10;
4040 obj->ai=1;
4041 obj->damage=25;
4042 obj->cost=COSTFIGHTER*COSTFACTOR;
4043
4044 /* NewWeapon(&obj->weapon1,CANNON8); */
4045 /* NewWeapon(&obj->weapon2,CANNON9); */
4046 break;
4047 case QUEEN: /* cargo queen ship */
4048 obj->radar=3*RADAR_RANGE;
4049 obj->gas_max=2000;
4050 obj->gas=obj->gas_max;
4051 obj->shield=0.9;
4052 obj->state=90;
4053 obj->mass=MASSQUEEN;
4054 obj->cargo.capacity=100;
4055 obj->radio=20;
4056 obj->ai=1;
4057 obj->damage=25;
4058 obj->cost=COSTQUEEN*COSTFACTOR;
4059 break;
4060
4061 case FREIGHTER: /* FREIGHTER */
4062 obj->radar=2*RADAR_RANGE;
4063 obj->gas_max=2000;
4064 obj->gas=obj->gas_max;
4065 obj->shield=0.8;
4066 obj->state=90;
4067 obj->mass=MASSFREIGHTER;
4068 obj->cargo.capacity=200;
4069 obj->radio=20;
4070 obj->ai=1;
4071 obj->damage=25;
4072 obj->cost=COSTFREIGHTER*COSTFACTOR;
4073 break;
4074
4075 case SATELLITE: /* SATELLITE: */
4076 obj->radar=3*RADAR_RANGE;
4077 obj->durable=TRUE;
4078 obj->life=LIFESATELLITE;
4079 obj->gas_max=500;
4080 obj->gas=obj->gas_max;
4081 obj->shield=0;
4082 obj->state=99;
4083 obj->mass=MASSSATELLITE;
4084 obj->damage=10;
4085 obj->cargo.capacity=0;
4086 obj->radio=5;
4087 obj->ai=1;
4088 obj->in=in;
4089 obj->planet=NULL;
4090 obj->cost=COSTSATELLITE*COSTFACTOR;
4091 break;
4092 case TOWER: /* TOWER: */
4093 /* obj->radar=8*RADAR_RANGE; */
4094 obj->gas_max=1000;
4095 obj->gas=obj->gas_max;
4096 obj->shield=0.5;
4097 obj->state=99;
4098 obj->mass=MASSTOWER;
4099 obj->cargo.capacity=0;
4100 obj->radio=10;
4101 obj->ai=1;
4102 obj->in=in;
4103 obj->damage=25;
4104 obj->cost=COSTTOWER*COSTFACTOR;
4105 break;
4106 case PILOT: /* PILOT */
4107 obj->gas_max=0;
4108 obj->gas=obj->gas_max;
4109 /* obj->shield=0; keep shield */
4110 obj->state=100;
4111 obj->mass=MASSPILOT;
4112 obj->cargo.capacity=0;
4113 obj->radio=10;
4114 obj->ai=0;
4115 /* obj->habitat=obj->parent->habitat; */
4116 obj->in=in;
4117 obj->damage=5;
4118 obj->cost=COSTPILOT*COSTFACTOR;
4119 break;
4120
4121 case GOODS: /* GOODS */
4122 obj->radar=0;
4123 obj->durable=TRUE;
4124 obj->life=LIFEGOODS;
4125 obj->gas_max=0;
4126 obj->gas=obj->gas_max;
4127 obj->shield=0;
4128 obj->state=99;
4129 obj->mass=MASSGOODS;
4130 obj->damage=5;
4131 obj->cargo.capacity=0;
4132 obj->radio=2;
4133 obj->ai=0;
4134 obj->in=in;
4135 obj->planet=NULL;
4136 obj->cost=COSTGOODS*COSTFACTOR;
4137 break;
4138
4139 default:
4140 fprintf(stderr,"ERROR ShipProperties(): unknown subtype %d\n",stype);
4141 exit(-1);
4142 break;
4143 }
4144 }
4145
4146
CreatePilot(Object * obj)4147 int CreatePilot( Object *obj){
4148
4149 /*
4150 when the ship obj is destroyed and it has a survival pod it is
4151 ejected.
4152 returns:
4153 0 if the ship has not a survival pod
4154 1 if its created.
4155 */
4156
4157 if(obj==NULL)return(0);
4158 if((obj->items & ITSURVIVAL)==0)return(0);
4159
4160 /* check */
4161 if(obj->type==SHIP && obj->subtype!=FIGHTER){
4162 fprintf(stderr,"ERROR in CreatePilot() type: %d stype: %d\n",obj->type,obj->subtype);
4163 fprintf(stderr,"\t pilot not created\n");
4164 return(0);
4165 }
4166
4167 obj->gas=500;
4168 if(obj->habitat==H_PLANET){
4169 obj->y+=20;
4170 obj->vy+=10;
4171 if(obj->vy<10)obj->vy=10;
4172 obj->mode=NAV;
4173 }
4174 if(obj->habitat==H_SPACE){
4175 obj->vx=obj->vx*.65+4*Random(-1)-2;
4176 obj->vy=obj->vy*.65+4*Random(-1)-2;
4177 }
4178
4179 obj->subtype=PILOT;
4180 ShipProperties(obj,obj->subtype,obj->in);
4181 obj->items=0;
4182 obj->ai=0;
4183 obj->accel=0;
4184 obj->ang_a=0;
4185 obj->damage=5;
4186 obj->durable=TRUE;
4187 obj->life=LIFEPILOT;
4188 obj->radio=10;
4189
4190 obj->state=100;
4191 obj->weapon0.n=0;
4192 obj->weapon1.n=0;
4193 obj->weapon2.n=0;
4194 return(1);
4195 }
4196
4197
CountSelected(struct HeadObjList * lh,int player)4198 int CountSelected(struct HeadObjList *lh,int player){
4199 /*
4200 printf the selected ships
4201 return the number of selected ships
4202 */
4203
4204 struct ObjList *ls;
4205 int n=0;
4206
4207 if(lh==NULL)return(0);
4208 ls=lh->list;
4209 while(ls!=NULL){
4210 if(ls->obj->selected==TRUE && ls->obj->player==player){
4211 n++;
4212 }
4213 ls=ls->next;
4214 }
4215 return n;
4216 }
CountNSelected(struct HeadObjList * lh,int player)4217 int CountNSelected(struct HeadObjList *lh,int player){
4218 /*
4219 Count the number of selected objects.
4220 returns:
4221 0 if no objects selected.
4222 1 one object selected.
4223 2 more than one object selected.
4224 */
4225
4226 struct ObjList *ls;
4227 int n=0;
4228
4229 ls=lh->list;
4230 while(ls!=NULL){
4231 if(ls->obj->player!=player || ls->obj->type!=SHIP){ls=ls->next;continue;}
4232 if(ls->obj->selected==TRUE){
4233 n++;
4234 if(n>1)return(2);
4235 }
4236 ls=ls->next;
4237 }
4238 return(n);
4239 }
4240
4241
FirstSelected(struct HeadObjList * lh,int player)4242 Object *FirstSelected(struct HeadObjList *lh,int player){
4243 /*
4244 printf the selected ships
4245 return the first selected ship
4246 */
4247
4248 struct ObjList *ls;
4249
4250 if(lh==NULL)return(0);
4251 ls=lh->list;
4252 while(ls!=NULL){
4253 if(ls->obj->selected==TRUE && ls->obj->player==player){
4254 return(ls->obj);
4255 }
4256 ls=ls->next;
4257 }
4258 return(NULL);
4259 }
4260
Distance2(Object * obj1,Object * obj2)4261 float Distance2(Object *obj1,Object *obj2){
4262 /*
4263 version 0.2
4264 Calc the distance between 2 objects.
4265 Returns:
4266 distance pow 2
4267 */
4268
4269 float x1,x2,y1,y2,rx,ry,r2;
4270
4271 if(obj1==NULL)return(-1);
4272 if(obj2==NULL)return(-1);
4273
4274 if(obj1->habitat==H_SHIP)obj1=obj1->in;
4275 if(obj2->habitat==H_SHIP)obj2=obj2->in;
4276
4277
4278 if(obj1->in==obj2->in){
4279 x1=obj1->x;
4280 y1=obj1->y;
4281 x2=obj2->x;
4282 y2=obj2->y;
4283 }
4284 else{
4285 switch(obj1->habitat){
4286 case H_PLANET:
4287 x1=obj1->in->x;
4288 y1=obj1->in->y;
4289 break;
4290 case H_SPACE:
4291 x1=obj1->x;
4292 y1=obj1->y;
4293 break;
4294 default:
4295 fprintf(stderr,"ERROR in AreEnemy() habitat unknown\n");
4296 exit(-1);
4297 }
4298
4299 switch(obj2->habitat){
4300 case H_PLANET:
4301 x2=obj2->in->x;
4302 y2=obj2->in->y;
4303 break;
4304 case H_SPACE:
4305 x2=obj2->x;
4306 y2=obj2->y;
4307 break;
4308 default:
4309 fprintf(stderr,"ERROR in AreEnemy() habitat unknown\n");
4310 exit(-1);
4311 }
4312 }
4313
4314 rx=x1 - x2;
4315 ry=y1 - y2;
4316 r2=rx*rx+ry*ry;
4317 return(r2);
4318 }
4319
GameOver(struct HeadObjList * lhead,struct Player * players,int player)4320 int GameOver(struct HeadObjList *lhead,struct Player *players,int player){
4321 /*
4322 Conditions for GAME OVER :
4323 -no ships or (only pilots and gold less than 1100)
4324 */
4325 int n=0;
4326 n=CountObjs(lhead,player,SHIP,-1);
4327 if(n==0)return(1);
4328
4329 if(players[player].gold<GetPrice(NULL,FIGHTER,ENGINE4,CANNON4)){
4330 if(n==CountObjs(lhead,player,SHIP,PILOT)){ /* there are only pilots */
4331 return(1);
4332 }
4333 }
4334 return(0);
4335 }
4336
CheckObjsId(void)4337 int CheckObjsId(void){
4338 /* check if 2 objects has the same id */
4339
4340 struct ObjList *ls;
4341 int *tabla;
4342 int i,j,n,id_i;
4343
4344 n=listheadobjs.n;
4345
4346 tabla=malloc(n*sizeof(int));
4347 if(tabla==NULL){
4348 fprintf(stderr,"ERROR in malloc Check()\n");
4349 exit(-1);
4350 }
4351
4352 for(i=0;i<n;i++){
4353 tabla[i]=0;
4354 }
4355
4356 ls=listheadobjs.list;
4357 for(i=0;i<n;i++){
4358 tabla[i]=ls->obj->id;
4359 ls=ls->next;
4360 }
4361
4362 for(i=0;i<n-1;i++){
4363 id_i=tabla[i];
4364 for(j=i+1;j<n;j++){
4365 if(tabla[j]==id_i && id_i !=-1){
4366 printf("Check(): indice duplicado: i: %d j:%d id:%d \n",i,j,id_i);
4367 }
4368 }
4369 }
4370 free(tabla);
4371 tabla=NULL;
4372 return(0);
4373 }
4374
4375
4376 /*********/
4377 /* Cargo */
4378 /*********/
4379
CargoAdd(Object * obj1,Object * obj2)4380 int CargoAdd(Object *obj1,Object *obj2){
4381 /*
4382 Add obj2 to obj1 cargo list
4383 returns:
4384 0 if there are no room, is already in list
4385 1 if obj2 is added
4386 */
4387
4388 struct Player *players;
4389
4390 players=GetPlayers();
4391
4392 if(obj1==NULL || obj2==NULL){
4393 return(0);
4394 }
4395
4396 if(CargoIsObj(obj1,obj2)){
4397 printf("CargoAdd: already in list\n");
4398 return(0);
4399 }
4400
4401 if(obj1->cargo.capacity==0)return(0);
4402
4403 if(obj1->cargo.mass + obj2->mass + obj2->cargo.mass > obj1->cargo.capacity){
4404 fprintf(stderr,"No room for %d in %d %d %d\n",
4405 obj2->id,obj1->id,
4406 obj2->mass+obj2->cargo.mass,obj1->cargo.capacity);
4407 return(0);
4408 }
4409
4410
4411 if(players[obj1->player].team != players[obj2->player].team){
4412 fprintf(stderr,"ERROR in CargoAdd()\n");
4413 fprintf(stderr,"\t%d %d %d %d, %d %d %d %d\n",
4414 players[obj1->player].team,obj1->player,obj1->type,obj1->subtype,
4415 players[obj2->player].team,obj2->player,obj2->type,obj2->subtype);
4416 exit(-1);
4417 }
4418
4419 if(obj1->cargo.hlist==NULL){
4420 obj1->cargo.hlist = malloc(sizeof(struct HeadObjList));
4421 if(obj1->cargo.hlist==NULL){
4422 fprintf(stderr,"ERROR in malloc CargoAdd\n");
4423 exit(-1);
4424 }
4425 MemUsed(MADD,sizeof(struct HeadObjList));
4426 obj1->cargo.hlist->n=0;
4427 obj1->cargo.hlist->update=0;
4428 obj1->cargo.hlist->list=NULL;
4429 }
4430
4431 Add2ObjList(obj1->cargo.hlist,obj2);
4432
4433 obj1->cargo.mass+=obj2->mass + obj2->cargo.mass;
4434
4435 obj1->cargo.n++;
4436
4437 return(1);
4438 }
4439
4440
CargoGet(Object * obj1,int type,int subtype)4441 Object *CargoGet(Object *obj1,int type,int subtype){
4442
4443 /*
4444 Remove the first obj of type type from obj1 cargo list
4445 returns:
4446 a pointer to the removed object.
4447 */
4448
4449 struct ObjList *ls;
4450 Object *obj0;
4451
4452 if(obj1==NULL){
4453 return(NULL);
4454 }
4455 if(obj1->cargo.hlist==NULL){
4456 return(NULL);
4457 }
4458
4459 ls=obj1->cargo.hlist->list;
4460 while(ls!=NULL){
4461
4462 if(ls->obj->type==type && ls->obj->subtype==subtype){
4463 obj0=ls->obj;
4464 CargoRem(obj1,ls->obj);
4465 return(obj0);
4466 }
4467 ls=ls->next;
4468 }
4469 return(NULL);
4470 }
4471
4472
4473
CargoRem(Object * obj1,Object * obj2)4474 int CargoRem(Object *obj1,Object *obj2){
4475
4476 /*
4477 Remove obj2 from obj1 cargo list
4478 returns:
4479 the number of elements removed.
4480 */
4481
4482 struct ObjList *ls0,*ls;
4483
4484 if(obj1==NULL){
4485 return(0);
4486 }
4487 if(obj2==NULL){
4488 return(0);
4489 }
4490 if(obj1->cargo.hlist==NULL){
4491 return(0);
4492 }
4493
4494 ls=obj1->cargo.hlist->list;
4495 ls0=ls;
4496
4497
4498 while(ls!=NULL){
4499
4500 if(ls->obj==obj2){
4501 if(ls==ls0){ /* first element */
4502 obj1->cargo.hlist->list=ls->next;
4503 free(ls);
4504 ls=NULL;
4505 obj1->cargo.n--;
4506 obj1->cargo.mass-=obj2->mass-obj2->cargo.mass;
4507 if(obj1->cargo.n==0){
4508 free(obj1->cargo.hlist);
4509 obj1->cargo.hlist=NULL;
4510 }
4511 return(1);
4512 }
4513 ls0->next=ls->next;
4514 obj1->cargo.n--;
4515 obj1->cargo.mass-=obj2->mass-obj2->cargo.mass;
4516 free(ls);
4517 ls=NULL;
4518 if(obj1->cargo.n==0){
4519 free(obj1->cargo.hlist);
4520 obj1->cargo.hlist=NULL;
4521 }
4522 return(1);
4523 }
4524 ls0=ls;
4525 ls=ls->next;
4526 }
4527 return(0);
4528 }
4529
4530
CargoCheck(struct HeadObjList * hol,Object * cvobj)4531 void CargoCheck(struct HeadObjList *hol,Object *cvobj){
4532 /*
4533 check if destroyed or solded ship has objects.
4534 */
4535
4536 struct ObjList *ls;
4537 int sw=0;
4538 int gnet;
4539 int proc=0;
4540 struct Player *players;
4541
4542 players=GetPlayers();
4543
4544 ls=hol->list;
4545 gnet=GameParametres(GET,GNET,0);
4546 proc=GetProc();
4547
4548 while(ls!=NULL){
4549 sw=0;
4550 if(proc!=players[ls->obj->player].proc){ls=ls->next;continue;}
4551
4552 if(ls->obj->state<=0){
4553 sw=1;
4554 }
4555
4556 if(sw&& (ls->obj->cargo.hlist!=NULL)){
4557 CargoEjectObjs(ls->obj,-1,-1);
4558 /* ls->obj->items=(ls->obj->items)&(~ITPILOT); */
4559 }
4560
4561 /***** ship destroyed Create Pilot****/
4562 if(sw && (ls->obj->items & ITSURVIVAL)){
4563 sw=0;
4564 /* GetPointsObj(hol,players,ls->obj);/\* points and experience *\/ */
4565 if(CreatePilot(ls->obj)){
4566 Explosion(&listheadobjs,cvobj,ls->obj,0);
4567 #if SOUND
4568 if(ls->obj->habitat==H_PLANET)
4569 Play(ls->obj,EXPLOSION0,1);
4570 #endif
4571 if(ls->obj->player==actual_player){
4572 printf("%s %d\n",GetLocale(L_EJECTING),ls->obj->pid);
4573 }
4574 }
4575
4576 DelAllOrder(ls->obj);
4577 if(gnet==TRUE){
4578 ls->obj->modified=SENDOBJALL;
4579 }
4580 }
4581 ls=ls->next;
4582 }
4583 return;
4584 }
4585
4586
CargoDestroy(Object * obj)4587 int CargoDestroy(Object *obj){
4588 /*
4589 use when load a game
4590 remove all the cargo list
4591 returns:
4592 the number of elements removed from list.
4593 */
4594 struct ObjList *ls,*ls0;
4595 int n=0;
4596
4597 if(obj==NULL){
4598 return(0);
4599 }
4600 if(obj->cargo.hlist==NULL){
4601 return(0);
4602 }
4603
4604 ls=obj->cargo.hlist->list;
4605
4606 while(ls!=NULL){
4607 n++;
4608 ls0=ls;
4609
4610 /* ls->obj->in=obj->in; */
4611 /* ls->obj->habitat=obj->habitat; */
4612
4613 ls=ls->next;
4614 free(ls0);
4615 ls0= NULL;
4616 }
4617 free(obj->cargo.hlist);
4618 obj->cargo.hlist=NULL;
4619 obj->cargo.n=0;
4620 obj->cargo.mass=0;
4621 return(n);
4622 }
4623
4624
4625
CargoEjectObjs(Object * obj,int type,int subtype)4626 int CargoEjectObjs(Object *obj,int type,int subtype){
4627 /*
4628 Eject objects from ship obj cargo list.
4629
4630 if obj is dead:
4631 obj LANDED: Rescue pilots, destroy other objects.
4632 obj is NAVigating: eject all.
4633
4634 if obj is not dead:
4635 obj LANDED: Rescue pilots, keep other objects.
4636 obj is NAVigating: eject all.
4637
4638 if type and subtype are different of -1: only eject that type objects.
4639
4640 returns:
4641 the number of objects ejected.
4642 */
4643
4644 struct ObjList *ls;
4645 Object *obj1; /* object in cargo list */
4646 Segment *s;
4647 float r;
4648 int n=0;
4649 int gnet;
4650 int sw=0;
4651
4652 int rescuepilots=0;
4653 int keepothers=0;
4654 int destroyothers=0;
4655 int ejectall=0;
4656
4657 if(obj==NULL)return(0);
4658 if(obj->cargo.hlist==NULL)return(0);
4659
4660
4661 if(type!=-1 && subtype !=-1)sw=1; /* eject all */
4662 gnet=GameParametres(GET,GNET,0);
4663 ls=obj->cargo.hlist->list;
4664 while(ls!=NULL){
4665
4666 obj1=ls->obj;
4667 if(obj1->in!=obj){
4668 fprintf(stderr,"ERROR CargoEjectObjs(): not in. Ejecting anyway...\n");
4669 }
4670 if(sw){
4671 if(obj1->type!=type || obj1->subtype!=subtype){
4672 ls=ls->next;continue;
4673 }
4674 }
4675
4676 switch(obj->mode){
4677 case LANDED:
4678 if(obj->state>0){
4679 rescuepilots=1;
4680 keepothers=1;
4681 }
4682 else{
4683 rescuepilots=1;
4684 destroyothers=1;
4685 }
4686 break;
4687 case NAV:
4688 ejectall=1;
4689 break;
4690 case SOLD:
4691 rescuepilots=1;
4692 destroyothers=1;
4693 break;
4694 default:
4695 fprintf(stderr,"Not implemented. CargoEjectObjs() %d\n",obj->mode);
4696 exit(-1);
4697 break;
4698
4699 }
4700
4701 if(ejectall){
4702 obj1->in=obj->in;
4703 obj1->planet=NULL;
4704 obj1->habitat=obj->habitat;
4705 obj1->mode=NAV;
4706 obj1->x=obj->x;
4707 obj1->y=obj->y;
4708 obj1->vx=0.75*obj->vx+6*Random(-1)-3;
4709 if(obj->habitat==H_PLANET){
4710 obj1->vy=fabs(0.75*obj->vy+6*Random(-1)-3)+10;
4711 }
4712 else{
4713 obj1->vy=0.75*obj->vy+6*Random(-1)-3;
4714 }
4715 obj1->a=obj->a;
4716 obj1->ai=0;
4717 obj1->items=0;
4718 if(obj1->player==actual_player)printf("Pilot %d ejected from ship %d\n",obj1->pid,obj->pid);
4719
4720 DelAllOrder(obj1);
4721 CargoRem(obj,obj1);
4722 if(gnet==TRUE){
4723 SetModified(obj1,SENDOBJALL);
4724 if(obj1->modified!=SENDOBJALL){
4725 printf("PILOT EJECT mod: %d\n",obj1->modified);
4726 }
4727 }
4728 n++;
4729 ls=ls->next;continue;
4730 }
4731
4732
4733
4734 if(obj1->type==SHIP && obj1->subtype==PILOT){
4735 if(rescuepilots){
4736 s=LandZone(obj->in->planet);
4737
4738 if(s==NULL){
4739 fprintf(stderr,"ERROR EjectPilots(): Segment==NULL\n");
4740 exit(-1);
4741 }
4742 r=s->x1-s->x0-2*obj1->radio;
4743 obj1->in=obj->in;
4744 obj1->habitat=H_PLANET;
4745 obj1->experience=0;
4746 obj1->pexperience=0;
4747 obj1->planet=NULL;
4748 obj1->mode=LANDED;
4749 obj1->x=s->x0+obj1->radio+r*(Random(-1));
4750 obj1->y=obj->y;
4751 obj1->x0=obj1->x;
4752 obj1->y0=obj1->y;
4753 obj1->accel=0;
4754 obj1->ang_v=obj1->ang_a=0;
4755 obj1->vx=obj1->vy=0;
4756 obj1->a=0;
4757 obj1->ai=0;
4758 obj1->items=0;
4759 /* pilot->selected=FALSE; */
4760 Experience(obj,obj1->level*30); /* experience for rescue a pilot*/
4761 if(obj1->player==actual_player){
4762 printf("%s %d %s %d\n",
4763 GetLocale(L_PILOT),
4764 obj1->pid,
4765 GetLocale(L_SAVEDINPLANET),
4766 obj1->in->id);
4767 }
4768 DelAllOrder(obj1);
4769 CargoRem(obj,obj1);
4770 if(gnet==TRUE){
4771 SetModified(obj1,SENDOBJALL);
4772 }
4773 n++;
4774
4775 }
4776 }
4777 else{ /* it is not a PILOT */
4778 if(keepothers){
4779
4780 }
4781 if(destroyothers){
4782 /* destroy rest of the objects */
4783 obj1->in=obj->in;
4784 obj1->planet=NULL;
4785 obj1->habitat=obj->habitat;
4786 obj1->mode=NAV;
4787 obj1->state=0;
4788 DelAllOrder(obj1);
4789 CargoRem(obj,obj1);
4790 printf("OBJ %d EJECT %d\n",obj1->pid,obj->subtype);
4791 if(gnet==TRUE){
4792 SetModified(obj1,SENDOBJALL);
4793 if(obj1->modified!=SENDOBJALL){
4794 printf("OBJ EJECT mod: %d\n",obj1->modified);
4795 }
4796 }
4797 n++;
4798 }
4799 }
4800 ls=ls->next;
4801 }
4802 return(n);
4803 }
4804
4805
CargoIsObj(Object * obj,Object * obj2)4806 int CargoIsObj(Object *obj,Object *obj2){
4807 /*
4808 look for obj2 in obj cargo list
4809 returns:
4810 1 if is in the list
4811 0 if not.
4812 */
4813 struct ObjList *ls;
4814
4815 if(obj->cargo.hlist==NULL || obj==NULL || obj2==NULL){
4816 return(0);
4817 }
4818
4819 if(obj->cargo.n<=0){
4820 fprintf(stderr,"ERROR in cargo list %d %d (%d,%d) %f\n",
4821 obj->player,obj->id,
4822 obj->type,obj->subtype,
4823 obj->state);
4824 fprintf(stderr,"\tERROR in cargo list %d %d (%d,%d) %f\n",
4825 obj2->player,obj2->id,
4826 obj2->type,obj2->subtype,
4827 obj2->state);
4828 }
4829 ls=obj->cargo.hlist->list;
4830
4831 while(ls!=NULL){
4832 if(ls->obj==obj2)return(1);
4833 ls=ls->next;
4834 }
4835 return(0);
4836 }
4837
4838
CargoPrint(Object * obj)4839 int CargoPrint(Object *obj){
4840 /*
4841 Print cargo listremove all the cargo list
4842 returns:
4843 the number of elements of the list.
4844 */
4845 struct ObjList *ls;
4846 int n=0;
4847
4848 if(obj==NULL){
4849 return(0);
4850 }
4851 if(obj->cargo.hlist==NULL){
4852 printf("cargo: %d %d(%d)\n",obj->id,obj->pid,obj->cargo.n);
4853 return(0);
4854 }
4855
4856 ls=obj->cargo.hlist->list;
4857
4858 printf("cargo: %d (%d,%d,%d)->",obj->id,
4859 obj->cargo.mass,obj->cargo.capacity,
4860 obj->cargo.n);
4861 while(ls!=NULL){
4862 n++;
4863 printf("%d %d,",ls->obj->id,ls->obj->pid);
4864 ls=ls->next;
4865 }
4866 printf("\n");
4867 return(n);
4868 }
4869
CargoGetMass(Object * obj)4870 int CargoGetMass(Object *obj){
4871 /*
4872 Get the total mass of the objects in cargo. Don't count goods
4873 returns:
4874 the mass of cargo.
4875 */
4876 struct ObjList *ls;
4877 int mass=0;
4878
4879 if(obj==NULL){
4880 return(0);
4881 }
4882 if(obj->cargo.hlist==NULL){
4883 return(0);
4884 }
4885
4886 ls=obj->cargo.hlist->list;
4887
4888 while(ls!=NULL){
4889 mass+=ls->obj->mass;
4890 ls=ls->next;
4891 }
4892 return(mass);
4893 }
4894
4895
4896
CargoBuild(Object * obj)4897 int CargoBuild(Object *obj){
4898
4899 /*
4900 Build the cargo list of object obj
4901 */
4902
4903 struct ObjList *ls;
4904
4905 ls=listheadobjs.list;
4906 while(ls!=NULL){
4907 switch(ls->obj->habitat){
4908 case H_PLANET:
4909 case H_SPACE:
4910 break;
4911 case H_SHIP:
4912 if(ls->obj->in==obj){
4913 CargoAdd(obj,ls->obj);
4914 }
4915 break;
4916 default:
4917 exit(-1);
4918 }
4919 ls=ls->next;
4920 }
4921
4922
4923 return(0);
4924 }
4925
4926