[56] | 1 | /* |
---|
| 2 | * Abuse - dark 2D side-scrolling platform game |
---|
| 3 | * Copyright (c) 1995 Crack dot Com |
---|
| 4 | * |
---|
| 5 | * This software was released into the Public Domain. As with most public |
---|
| 6 | * domain software, no warranty is made or implied by Crack dot Com or |
---|
| 7 | * Jonathan Clark. |
---|
| 8 | */ |
---|
| 9 | |
---|
| 10 | #include "config.h" |
---|
| 11 | |
---|
| 12 | #if (defined(__MACH__) || !defined(__APPLE__)) |
---|
| 13 | #include <sys/stat.h> |
---|
| 14 | #endif |
---|
| 15 | |
---|
| 16 | #include <limits.h> |
---|
| 17 | #include <time.h> |
---|
| 18 | |
---|
[2] | 19 | #include "light.hpp" |
---|
| 20 | #include "level.hpp" |
---|
| 21 | #include "game.hpp" |
---|
| 22 | #include "intsect.hpp" |
---|
| 23 | #include "lisp.hpp" |
---|
| 24 | #include "dprint.hpp" |
---|
| 25 | #include "particle.hpp" |
---|
| 26 | #include "objects.hpp" |
---|
| 27 | #include "jrand.hpp" |
---|
| 28 | #include "macs.hpp" |
---|
| 29 | #include "clisp.hpp" |
---|
| 30 | #include "status.hpp" |
---|
| 31 | #include "dev.hpp" |
---|
| 32 | #include "demo.hpp" |
---|
| 33 | #include "pcxread.hpp" |
---|
| 34 | #include "profile.hpp" |
---|
| 35 | #include "sbar.hpp" |
---|
| 36 | #include "cop.hpp" |
---|
| 37 | #include "nfserver.hpp" |
---|
| 38 | #include "lisp_gc.hpp" |
---|
| 39 | |
---|
| 40 | level *current_level; |
---|
| 41 | |
---|
| 42 | game_object *level::attacker(game_object *who) |
---|
| 43 | { |
---|
[16] | 44 | int32_t d=0x7fffffff; |
---|
[2] | 45 | game_object *c=NULL; |
---|
| 46 | view *f=the_game->first_view; |
---|
| 47 | for (;f;f=f->next) |
---|
| 48 | { |
---|
| 49 | if (f->focus) |
---|
| 50 | { |
---|
[16] | 51 | int32_t tmp_d=abs(f->focus->x-who->x)+abs(f->focus->y-who->y); |
---|
[2] | 52 | if (tmp_d<d) |
---|
| 53 | { |
---|
| 54 | d=tmp_d; |
---|
| 55 | c=f->focus; |
---|
| 56 | } |
---|
| 57 | } |
---|
| 58 | } |
---|
| 59 | CONDITION(c,"no attacker found"); |
---|
| 60 | return c; |
---|
| 61 | } |
---|
| 62 | |
---|
| 63 | |
---|
| 64 | |
---|
| 65 | int level::is_attacker(game_object *who) |
---|
| 66 | { |
---|
| 67 | return who->controller()!=NULL; |
---|
| 68 | } |
---|
| 69 | |
---|
| 70 | |
---|
| 71 | game_object *level::main_character() |
---|
| 72 | { |
---|
| 73 | return the_game->first_view->focus; |
---|
| 74 | } |
---|
| 75 | |
---|
| 76 | void level::load_fail() |
---|
| 77 | { |
---|
| 78 | if (map_fg) jfree(map_fg); map_fg=NULL; |
---|
| 79 | if (map_bg) jfree(map_bg); map_bg=NULL; |
---|
| 80 | if (Name) jfree(Name); Name=NULL; |
---|
| 81 | |
---|
| 82 | first_active=NULL; |
---|
| 83 | view *f=player_list; |
---|
| 84 | for (;f;f=f->next) |
---|
| 85 | if (f->focus) |
---|
| 86 | current_level->remove_object(f->focus); |
---|
| 87 | |
---|
| 88 | while (first) |
---|
| 89 | { |
---|
| 90 | first_active=first; |
---|
| 91 | first=first->next; |
---|
| 92 | if (dev_cont) |
---|
| 93 | dev_cont->notify_deleted_object(first_active); |
---|
| 94 | delete first_active; |
---|
| 95 | } |
---|
| 96 | |
---|
| 97 | while (area_list) |
---|
| 98 | { |
---|
| 99 | area_controller *l=area_list; |
---|
| 100 | area_list=area_list->next; |
---|
| 101 | delete l; |
---|
| 102 | } |
---|
| 103 | |
---|
| 104 | last=NULL; |
---|
| 105 | delete_panims(); |
---|
| 106 | delete_all_lights(); |
---|
| 107 | |
---|
| 108 | } |
---|
| 109 | |
---|
| 110 | level::~level() |
---|
| 111 | { |
---|
| 112 | load_fail(); |
---|
| 113 | if (attack_list) jfree(attack_list); |
---|
| 114 | if (target_list) jfree(target_list); |
---|
| 115 | if (block_list) jfree(block_list); |
---|
| 116 | if (all_block_list) jfree(all_block_list); |
---|
| 117 | if (first_name) jfree(first_name); |
---|
| 118 | } |
---|
| 119 | |
---|
| 120 | void level::restart() |
---|
| 121 | { |
---|
| 122 | view *f; |
---|
| 123 | game_object *found=NULL,*o; |
---|
| 124 | f=the_game->first_view; |
---|
| 125 | for (o=first;f && o;o=o->next) |
---|
| 126 | { |
---|
| 127 | while (f && !f->focus) f=f->next; |
---|
| 128 | if (f) |
---|
| 129 | { |
---|
| 130 | if (!strcmp(object_names[o->otype],"START")) |
---|
| 131 | { |
---|
| 132 | if (!found) found=o; |
---|
| 133 | f->focus->x=o->x; |
---|
| 134 | f->focus->y=o->y; |
---|
| 135 | f->focus->set_hp(get_ability(f->focus->otype,start_hp)); |
---|
| 136 | f->focus->set_state(stopped); |
---|
| 137 | f=f->next; |
---|
| 138 | } |
---|
| 139 | } |
---|
| 140 | } |
---|
| 141 | while (f) |
---|
| 142 | { |
---|
| 143 | if (f->focus) |
---|
| 144 | { |
---|
| 145 | f->focus->x=found->x; |
---|
| 146 | f->focus->y=found->y; |
---|
| 147 | f->focus->set_hp(get_ability(f->focus->otype,start_hp)); |
---|
| 148 | f->focus->set_state(stopped); |
---|
| 149 | } |
---|
| 150 | f=f->next; |
---|
| 151 | } |
---|
| 152 | } |
---|
| 153 | |
---|
| 154 | |
---|
| 155 | void level::next_focus() |
---|
| 156 | { |
---|
| 157 | /* int i; |
---|
| 158 | for (i=0;i<total_objs;i++) |
---|
| 159 | if (obj[i]==the_game->first_view->focus) |
---|
| 160 | { |
---|
| 161 | int tries=total_objs; |
---|
| 162 | do |
---|
| 163 | { |
---|
| 164 | i++; |
---|
| 165 | if (i==total_objs) |
---|
| 166 | i=0; |
---|
| 167 | the_game->first_view->focus=obj[i]; |
---|
| 168 | } while ((!the_game->first_view->focus->is_playable() || |
---|
| 169 | the_game->first_view->focus->hp<=0) && tries--); |
---|
| 170 | return ; |
---|
| 171 | } */ |
---|
| 172 | } |
---|
| 173 | |
---|
| 174 | void level::unactivate_all() |
---|
| 175 | { |
---|
| 176 | first_active=NULL; |
---|
| 177 | game_object *o=first; |
---|
| 178 | attack_total=0; // reset the attack list |
---|
| 179 | target_total=0; |
---|
| 180 | block_total=0; |
---|
| 181 | all_block_total=0; |
---|
| 182 | |
---|
| 183 | for (;o;o=o->next) |
---|
| 184 | o->active=0; |
---|
| 185 | } |
---|
| 186 | |
---|
| 187 | |
---|
| 188 | void level::pull_actives(game_object *o, game_object *&last_active, int &t) |
---|
| 189 | { |
---|
| 190 | int i=o->total_objects(); |
---|
| 191 | for (;i;i--) // pull any linked object into active list |
---|
| 192 | { |
---|
| 193 | game_object *other=o->get_object(i-1); |
---|
| 194 | if (!other->active) |
---|
| 195 | { |
---|
| 196 | other->active=1; |
---|
| 197 | if (other->can_block()) // if object can block other player, keep a list for fast testing |
---|
| 198 | { |
---|
| 199 | add_block(other); |
---|
| 200 | add_all_block(other); |
---|
| 201 | } else if (other->hurtable()) |
---|
| 202 | add_all_block(other); |
---|
| 203 | |
---|
| 204 | t++; |
---|
| 205 | last_active->next_active=other; |
---|
| 206 | last_active=other; |
---|
| 207 | pull_actives(o,last_active,t); |
---|
| 208 | } |
---|
| 209 | } |
---|
| 210 | } |
---|
| 211 | |
---|
[16] | 212 | int level::add_actives(int32_t x1, int32_t y1, int32_t x2, int32_t y2) |
---|
[2] | 213 | { |
---|
| 214 | int t=0; |
---|
| 215 | game_object *last_active=NULL; |
---|
| 216 | if (first_active) |
---|
| 217 | for (last_active=first_active;last_active->next_active;last_active=last_active->next_active); |
---|
| 218 | |
---|
| 219 | game_object *o=first; |
---|
| 220 | for (;o;o=o->next) |
---|
| 221 | { |
---|
| 222 | if (!o->active) |
---|
| 223 | { |
---|
[16] | 224 | int32_t xr=figures[o->otype]->rangex, |
---|
[2] | 225 | yr=figures[o->otype]->rangey; |
---|
| 226 | |
---|
| 227 | if (o->x+xr>=x1 && o->x-xr<=x2 && o->y+yr>=y1 && o->y-yr<=y2) |
---|
| 228 | { |
---|
| 229 | |
---|
| 230 | if (o->can_block()) // if object can block other player, keep a list for fast testing |
---|
| 231 | { |
---|
| 232 | add_block(o); |
---|
| 233 | add_all_block(o); |
---|
| 234 | } else if (o->hurtable()) |
---|
| 235 | add_all_block(o); |
---|
| 236 | |
---|
| 237 | |
---|
| 238 | o->active=1; |
---|
| 239 | t++; |
---|
| 240 | if (!first_active) |
---|
| 241 | first_active=o; |
---|
| 242 | else |
---|
| 243 | last_active->next_active=o; |
---|
| 244 | last_active=o; |
---|
| 245 | |
---|
| 246 | pull_actives(o,last_active,t); |
---|
| 247 | } |
---|
| 248 | } |
---|
| 249 | } |
---|
| 250 | if (last_active) |
---|
| 251 | last_active->next_active=NULL; |
---|
| 252 | return t; |
---|
| 253 | } |
---|
| 254 | |
---|
| 255 | |
---|
[16] | 256 | int level::add_drawables(int32_t x1, int32_t y1, int32_t x2, int32_t y2) |
---|
[2] | 257 | { |
---|
| 258 | int t=0,ft=0; |
---|
| 259 | game_object *last_active=NULL; |
---|
| 260 | if (first_active) |
---|
| 261 | { |
---|
| 262 | for (last_active=first_active;last_active->next_active;last_active=last_active->next_active); |
---|
| 263 | } else ft=1; |
---|
| 264 | |
---|
| 265 | game_object *o=first; |
---|
| 266 | for (;o;o=o->next) |
---|
| 267 | { |
---|
| 268 | if (ft || !o->active) |
---|
| 269 | { |
---|
[16] | 270 | int32_t xr=figures[o->otype]->draw_rangex, |
---|
[2] | 271 | yr=figures[o->otype]->draw_rangey; |
---|
| 272 | |
---|
| 273 | if (o->x+xr>=x1 && o->x-xr<=x2 && o->y+yr>=y1 && o->y-yr<=y2) |
---|
| 274 | { |
---|
| 275 | t++; |
---|
| 276 | if (!first_active) |
---|
| 277 | first_active=o; |
---|
| 278 | else |
---|
| 279 | last_active->next_active=o; |
---|
| 280 | last_active=o; |
---|
| 281 | o->active=1; |
---|
| 282 | } else if (ft) o->active=0; // if this is the first pass, then mark objects not in this ranges as not active |
---|
| 283 | } |
---|
| 284 | } |
---|
| 285 | if (last_active) |
---|
| 286 | last_active->next_active=NULL; |
---|
| 287 | return t; |
---|
| 288 | } |
---|
| 289 | |
---|
| 290 | |
---|
| 291 | view *level::make_view_list(int nplayers) |
---|
| 292 | { |
---|
| 293 | int startable; |
---|
| 294 | CONDITION(nplayers>0,"make_view_list with <=0 players!\n"); |
---|
| 295 | view *f=NULL; |
---|
| 296 | int j,use_type=current_start_type; |
---|
| 297 | figures[use_type]->cache_in(); |
---|
| 298 | game_object *o,*last_start=NULL; |
---|
| 299 | int num=0; |
---|
| 300 | |
---|
| 301 | for (j=0,o=first;o && j<nplayers;o=o->next) |
---|
| 302 | { |
---|
| 303 | if (!strcmp(object_names[o->otype],"START")) |
---|
| 304 | { |
---|
| 305 | f=new view(create(use_type,o->x,o->y),f,num); num++; |
---|
| 306 | f->focus->set_controller(f); |
---|
| 307 | add_object_after(f->focus,o); |
---|
| 308 | j++; |
---|
| 309 | last_start=o; |
---|
| 310 | } |
---|
| 311 | } |
---|
| 312 | |
---|
| 313 | // if we couldn't find enough starts then create the rest of the players at the original start |
---|
| 314 | startable=j; // if we haven't created anyone yet, it's because we can't |
---|
| 315 | |
---|
| 316 | for (;j<nplayers;j++) |
---|
| 317 | { |
---|
| 318 | if (startable) |
---|
| 319 | { |
---|
| 320 | game_object *o=create(use_type,f->focus->x,f->focus->y); |
---|
| 321 | f=new view(o,f,num); num++; |
---|
| 322 | f->focus->set_controller(f); |
---|
| 323 | add_object_after(o,last_start); |
---|
| 324 | } |
---|
| 325 | else |
---|
| 326 | { |
---|
| 327 | f=new view(NULL,f,num); |
---|
| 328 | num++; |
---|
| 329 | } |
---|
| 330 | } |
---|
| 331 | return f; |
---|
| 332 | } |
---|
| 333 | |
---|
| 334 | void level::wall_push() |
---|
| 335 | { |
---|
[16] | 336 | int32_t sx1,sy1,sx2,sy2,xv,yv; |
---|
[2] | 337 | game_object *o=first_active; |
---|
| 338 | for (;o;o=o->next_active) |
---|
| 339 | { |
---|
| 340 | if (o->pushable()) |
---|
| 341 | { |
---|
| 342 | o->picture_space(sx1,sy1,sx2,sy2); |
---|
| 343 | xv=sx1-o->x; |
---|
| 344 | yv=0; |
---|
| 345 | o->try_move(o->x,o->y-1,xv,yv,1); // check for wall pushes on the left using feet |
---|
| 346 | if (xv!=sx1-o->x) // is the character in the wall? |
---|
| 347 | { |
---|
| 348 | xv=-xv; |
---|
| 349 | o->try_move(o->x,o->y-1,xv,yv,1); // see how far to the right we can push the character |
---|
| 350 | o->x+=xv; |
---|
| 351 | } else |
---|
| 352 | { |
---|
| 353 | xv=sx2-o->x; |
---|
| 354 | o->try_move(o->x,o->y-1,xv,yv,1); // now check the right of the character for a wall |
---|
| 355 | if (xv!=sx2-o->x) |
---|
| 356 | { |
---|
| 357 | xv=-xv; |
---|
| 358 | o->try_move(o->x,o->y-1,xv,yv,1); |
---|
| 359 | o->x+=xv; |
---|
| 360 | } |
---|
| 361 | } |
---|
| 362 | } |
---|
| 363 | } |
---|
| 364 | } |
---|
| 365 | |
---|
| 366 | |
---|
| 367 | void level::try_pushback(game_object *subject,game_object *target) |
---|
| 368 | { |
---|
| 369 | if (subject->pushable() && target->pushable() && |
---|
| 370 | subject->state!=dead && target->state!=dead && |
---|
| 371 | subject->state!=dieing && target->state!=dieing) |
---|
| 372 | { |
---|
| 373 | int b1=subject->push_range(),b2=target->push_range(); |
---|
| 374 | if (abs(subject->x-target->x)<b1+b2) |
---|
| 375 | { |
---|
[16] | 376 | int32_t tmove=b1+b2-abs(subject->x-target->x),xv,yv=0,xv2; |
---|
[2] | 377 | if (subject->x>target->x) |
---|
| 378 | xv=tmove/2; |
---|
| 379 | else xv=-tmove/2; |
---|
| 380 | xv2=-xv; |
---|
| 381 | |
---|
| 382 | subject->try_move(subject->x,subject->y,xv,yv,3); |
---|
| 383 | subject->x+=xv; |
---|
| 384 | |
---|
| 385 | yv=0; |
---|
| 386 | target->try_move(target->x,target->y,xv2,yv,3); |
---|
| 387 | target->x+=xv2; |
---|
| 388 | } |
---|
| 389 | } |
---|
| 390 | } |
---|
| 391 | |
---|
| 392 | /* |
---|
| 393 | void level::check_collisions() |
---|
| 394 | { |
---|
| 395 | game_object *target,*reciever=NULL; |
---|
[16] | 396 | int32_t sx1,sy1,sx2,sy2,tx1,ty1,tx2,ty2,hitx,hity, |
---|
[2] | 397 | s_centerx,t_centerx; |
---|
| 398 | |
---|
| 399 | for (game_object *subject=first_active;subject;subject=subject->next_active) |
---|
| 400 | { |
---|
| 401 | subject->picture_space(sx1,sy1,sx2,sy2); |
---|
| 402 | s_centerx=subject->x_center(); |
---|
| 403 | |
---|
| 404 | int hit=0; |
---|
| 405 | reciever=NULL; |
---|
| 406 | for (target=first_active;target;target=target->next_active) |
---|
| 407 | { |
---|
| 408 | if (target!=subject) |
---|
| 409 | { |
---|
| 410 | target->picture_space(tx1,ty1,tx2,ty2); |
---|
| 411 | |
---|
| 412 | if (!(sx2<tx1 || sx1>tx2 || sy1>ty2 || sy2<ty1)) // are they semi/overlapping? |
---|
| 413 | { |
---|
| 414 | try_pushback(subject,target); |
---|
| 415 | if (subject->can_hurt(target)) // see if we can hurt him before calculating |
---|
| 416 | { |
---|
| 417 | t_centerx=target->x_center(); |
---|
| 418 | point_list *s_hit,*t_damage; |
---|
| 419 | |
---|
| 420 | s_hit=subject->current_figure()->hit; |
---|
| 421 | t_damage=target->current_figure()->damage; |
---|
| 422 | |
---|
| 423 | unsigned char *s_dat=s_hit->data, |
---|
| 424 | *t_dat; |
---|
| 425 | int i,j; |
---|
| 426 | for (i=(int)s_hit->tot-1;i>0 && !hit;i--) |
---|
| 427 | { |
---|
| 428 | for (t_dat=t_damage->data,j=(int)t_damage->tot-1;j>0 && !hit;j--) |
---|
| 429 | { |
---|
[16] | 430 | int32_t x1,y1,x2,y2, // define the two line segments to check |
---|
[2] | 431 | xp1,yp1,xp2,yp2; |
---|
| 432 | |
---|
| 433 | xp1=target->x+target->tx(*t_dat); t_dat++; |
---|
| 434 | yp1=target->y+target->ty(*t_dat); t_dat++; |
---|
| 435 | xp2=target->x+target->tx(*t_dat); |
---|
| 436 | yp2=target->y+target->ty(t_dat[1]); |
---|
| 437 | |
---|
| 438 | x1=subject->x+subject->tx(s_dat[0]); |
---|
| 439 | y1=subject->y+subject->ty(s_dat[1]); |
---|
| 440 | x2=subject->x+subject->tx(s_dat[2]); |
---|
| 441 | y2=subject->y+subject->ty(s_dat[3]); |
---|
| 442 | |
---|
| 443 | |
---|
| 444 | // ok, now we know which line segemnts to check for intersection |
---|
| 445 | // now check to see if (x1,y1-x2,y2) intercest with (xp1,yp1-xp2,yp2) |
---|
| 446 | int _x2=x2,_y2=y2; |
---|
| 447 | setback_intersect(x1, y1, x2, y2, xp1, yp1, xp2, yp2,0); |
---|
| 448 | |
---|
| 449 | |
---|
| 450 | if (x2!=_x2 || _y2!=y2) |
---|
| 451 | { |
---|
| 452 | reciever=target; |
---|
| 453 | hitx=((x1+x2)/2+(xp1+xp2)/2)/2; |
---|
| 454 | hity=((y1+y1)/2+(yp1+yp2)/2)/2; |
---|
| 455 | } |
---|
| 456 | } |
---|
| 457 | s_dat+=2; |
---|
| 458 | } |
---|
| 459 | } |
---|
| 460 | } |
---|
| 461 | } |
---|
| 462 | } |
---|
| 463 | if (reciever) |
---|
| 464 | { |
---|
| 465 | reciever->do_damage((int)subject->current_figure()->hit_damage,subject,hitx,hity,0,0); |
---|
| 466 | subject->note_attack(reciever); |
---|
| 467 | hit=1; |
---|
| 468 | } |
---|
| 469 | } |
---|
| 470 | } |
---|
| 471 | */ |
---|
| 472 | |
---|
[16] | 473 | game_object *level::boundary_setback(game_object *subject, int32_t x1, int32_t y1, int32_t &x2, int32_t &y2) |
---|
[2] | 474 | { |
---|
| 475 | game_object *l=NULL; |
---|
[16] | 476 | int32_t tx1,ty1,tx2,ty2,t_centerx; |
---|
[2] | 477 | game_object *target=first_active; |
---|
| 478 | game_object **blist=block_list; |
---|
| 479 | int t=block_total; |
---|
| 480 | for (;t;t--,blist++) |
---|
| 481 | { |
---|
| 482 | target=*blist; |
---|
| 483 | if (target!=subject && (target->total_objects()==0 || target->get_object(0)!=subject)) |
---|
| 484 | { |
---|
| 485 | target->picture_space(tx1,ty1,tx2,ty2); |
---|
| 486 | if (!((x2<tx1 && x1<tx1) || (x1>tx2 && x2>tx2) || |
---|
| 487 | (y1>ty2 && y2>ty2) || (y1<ty1 && y2<ty1))) // are they semi/overlapping? |
---|
| 488 | { |
---|
| 489 | t_centerx=target->x_center(); |
---|
| 490 | boundary *t_damage; |
---|
| 491 | if (target->direction>0) |
---|
| 492 | t_damage=target->current_figure()->f_damage; |
---|
| 493 | else |
---|
| 494 | t_damage=target->current_figure()->b_damage; |
---|
| 495 | unsigned char *t_dat=t_damage->data,*ins=t_damage->inside; |
---|
| 496 | int iter=t_damage->tot-1; |
---|
| 497 | while(iter-->0) |
---|
| 498 | { |
---|
[16] | 499 | int32_t xp1=target->x+target->tx(*t_dat); t_dat++; |
---|
| 500 | int32_t yp1=target->y+target->ty(*t_dat); t_dat++; |
---|
| 501 | int32_t xp2=target->x+target->tx(*t_dat); |
---|
| 502 | int32_t yp2=target->y+target->ty(t_dat[1]); |
---|
[2] | 503 | |
---|
| 504 | // now check to see if (x1,y1-x2,y2) intercest with (xp1,yp1-xp2,yp2) |
---|
| 505 | if (*ins) |
---|
| 506 | { |
---|
| 507 | if (setback_intersect(x1,y1,x2,y2,xp1,yp1,xp2,yp2,1)) |
---|
| 508 | l=target; |
---|
| 509 | } |
---|
| 510 | else |
---|
| 511 | { |
---|
| 512 | if (setback_intersect(x1,y1,x2,y2,xp1,yp1,xp2,yp2,-1)) |
---|
| 513 | l=target; |
---|
| 514 | } |
---|
| 515 | ins++; |
---|
| 516 | |
---|
| 517 | } |
---|
| 518 | } |
---|
| 519 | } |
---|
| 520 | } |
---|
| 521 | return l; // return the last person we intersected |
---|
| 522 | } |
---|
| 523 | |
---|
| 524 | |
---|
[16] | 525 | game_object *level::all_boundary_setback(game_object *subject, int32_t x1, int32_t y1, int32_t &x2, int32_t &y2) |
---|
[2] | 526 | { |
---|
| 527 | game_object *l=NULL; |
---|
[16] | 528 | int32_t tx1,ty1,tx2,ty2,t_centerx; |
---|
[2] | 529 | game_object *target=first_active; |
---|
| 530 | game_object **blist=all_block_list; |
---|
| 531 | int t=all_block_total; |
---|
| 532 | for (;t;t--,blist++) |
---|
| 533 | { |
---|
| 534 | target=*blist; |
---|
| 535 | if (target!=subject && (target->total_objects()==0 || target->get_object(0)!=subject)) |
---|
| 536 | { |
---|
| 537 | target->picture_space(tx1,ty1,tx2,ty2); |
---|
| 538 | if (!((x2<tx1 && x1<tx1) || (x1>tx2 && x2>tx2) || |
---|
| 539 | (y1>ty2 && y2>ty2) || (y1<ty1 && y2<ty1))) // are they semi/overlapping? |
---|
| 540 | { |
---|
| 541 | t_centerx=target->x_center(); |
---|
| 542 | boundary *t_damage; |
---|
| 543 | if (target->direction>0) |
---|
| 544 | t_damage=target->current_figure()->f_damage; |
---|
| 545 | else |
---|
| 546 | t_damage=target->current_figure()->b_damage; |
---|
| 547 | unsigned char *t_dat=t_damage->data,*ins=t_damage->inside; |
---|
| 548 | int iter=t_damage->tot-1; |
---|
| 549 | while(iter-->0) |
---|
| 550 | { |
---|
[16] | 551 | int32_t xp1=target->x+target->tx(*t_dat); t_dat++; |
---|
| 552 | int32_t yp1=target->y+target->ty(*t_dat); t_dat++; |
---|
| 553 | int32_t xp2=target->x+target->tx(*t_dat); |
---|
| 554 | int32_t yp2=target->y+target->ty(t_dat[1]); |
---|
[2] | 555 | |
---|
| 556 | // now check to see if (x1,y1-x2,y2) intercest with (xp1,yp1-xp2,yp2) |
---|
| 557 | if (*ins) |
---|
| 558 | { |
---|
| 559 | if (setback_intersect(x1,y1,x2,y2,xp1,yp1,xp2,yp2,1)) |
---|
| 560 | l=target; |
---|
| 561 | } |
---|
| 562 | else |
---|
| 563 | { |
---|
| 564 | if (setback_intersect(x1,y1,x2,y2,xp1,yp1,xp2,yp2,-1)) |
---|
| 565 | l=target; |
---|
| 566 | } |
---|
| 567 | ins++; |
---|
| 568 | } |
---|
| 569 | } |
---|
| 570 | } |
---|
| 571 | } |
---|
| 572 | return l; // return the last person we intersected |
---|
| 573 | } |
---|
| 574 | |
---|
| 575 | |
---|
| 576 | //bFILE *rcheck=NULL,*rcheck_lp=NULL; |
---|
| 577 | |
---|
| 578 | void level::interpolate_draw_objects(view *v) |
---|
| 579 | { |
---|
[16] | 580 | int32_t old_x,old_y; |
---|
[2] | 581 | current_view=v; |
---|
| 582 | |
---|
| 583 | game_object *o=first_active; |
---|
| 584 | for (;o;o=o->next_active) |
---|
| 585 | { |
---|
| 586 | old_x=o->x; |
---|
| 587 | old_y=o->y; |
---|
| 588 | o->x=(o->last_x+o->x)/2; |
---|
| 589 | o->y=(o->last_y+o->y)/2; |
---|
| 590 | o->last_x=old_x; |
---|
| 591 | o->last_y=old_y; |
---|
| 592 | } |
---|
| 593 | |
---|
| 594 | for (o=first_active;o;o=o->next_active) |
---|
| 595 | o->draw(); |
---|
| 596 | |
---|
| 597 | for (o=first_active;o;o=o->next_active) |
---|
| 598 | { |
---|
| 599 | o->x=o->last_x; |
---|
| 600 | o->y=o->last_y; |
---|
| 601 | } |
---|
| 602 | } |
---|
| 603 | |
---|
| 604 | bFILE *rcheck=NULL,*rcheck_lp=NULL; |
---|
| 605 | |
---|
| 606 | extern int sshot_fcount,screen_shot_on; |
---|
| 607 | |
---|
| 608 | int level::tick() |
---|
| 609 | { |
---|
| 610 | game_object *o,*l=NULL, // l is last, used for delete |
---|
| 611 | *cur; // cur is current object, NULL if object deletes it's self |
---|
| 612 | int ret=1; |
---|
| 613 | |
---|
| 614 | if (profiling()) |
---|
| 615 | profile_reset(); |
---|
| 616 | |
---|
| 617 | /* // test to see if demo is in sync |
---|
| 618 | if (current_demo_mode()==DEMO_PLAY) |
---|
| 619 | { |
---|
| 620 | if (!rcheck) rcheck=open_file("rcheck","rb"); |
---|
[17] | 621 | int32_t x=rcheck->read_uint32(); |
---|
[2] | 622 | if (x!=rand_on) |
---|
| 623 | dprintf("off!\n"); |
---|
| 624 | } else if (current_demo_mode()==DEMO_RECORD) |
---|
| 625 | { |
---|
| 626 | if (!rcheck) |
---|
| 627 | { |
---|
| 628 | rcheck=open_file("rcheck","wb"); |
---|
| 629 | rcheck_lp=open_file("rcheck.lp","wb"); |
---|
| 630 | } |
---|
[17] | 631 | rcheck->write_uint32(rand_on); |
---|
[2] | 632 | } else |
---|
| 633 | { |
---|
| 634 | if (rcheck) |
---|
| 635 | { |
---|
| 636 | delete rcheck; |
---|
| 637 | rcheck=NULL; |
---|
| 638 | } |
---|
| 639 | if (rcheck_lp) |
---|
| 640 | { |
---|
| 641 | delete rcheck_lp; |
---|
| 642 | rcheck_lp=NULL; |
---|
| 643 | } |
---|
| 644 | }*/ |
---|
| 645 | |
---|
| 646 | for (o=first_active;o;) |
---|
| 647 | { |
---|
| 648 | o->last_x=o->x; |
---|
| 649 | o->last_y=o->y; |
---|
| 650 | cur=o; |
---|
| 651 | view *c=o->controller(); |
---|
| 652 | if (!(dev&SUSPEND_MODE) || c) |
---|
| 653 | { |
---|
| 654 | o->set_flags(o->flags()&(0xff-FLAG_JUST_HIT-FLAG_JUST_BLOCKED)); |
---|
| 655 | |
---|
| 656 | if (c) |
---|
| 657 | { |
---|
| 658 | area_controller *a,*smallest=NULL; |
---|
[16] | 659 | int32_t smallest_size=0xffffffff; |
---|
[2] | 660 | for (a=area_list;a;a=a->next) |
---|
| 661 | if (o->x>=a->x && o->y>=a->y && o->x<=a->x+a->w && o->y<=a->y+a->h) |
---|
| 662 | { |
---|
[16] | 663 | int32_t size=a->w*a->h; |
---|
[2] | 664 | if (size<smallest_size) |
---|
| 665 | { |
---|
| 666 | smallest=a; |
---|
| 667 | smallest_size=size; |
---|
| 668 | } |
---|
| 669 | } |
---|
| 670 | |
---|
| 671 | if (c->local_player()) |
---|
| 672 | { |
---|
| 673 | if (!shutdown_lighting) // should we initiate a lighting shutdown? |
---|
| 674 | { |
---|
| 675 | if (massive_frame_panic>30) |
---|
| 676 | { |
---|
| 677 | shutdown_lighting=100; |
---|
| 678 | shutdown_lighting_value=c->ambient; |
---|
| 679 | } |
---|
| 680 | } else if (massive_frame_panic) // do we need brighten towards 63? |
---|
| 681 | { |
---|
| 682 | if (shutdown_lighting_value<63) |
---|
| 683 | shutdown_lighting_value++; |
---|
| 684 | } else if (shutdown_lighting>1) // delay for some time before turning back on |
---|
| 685 | shutdown_lighting--; |
---|
| 686 | else if (shutdown_lighting_value!=c->ambient) // do we need to lower light toward real ambient? |
---|
| 687 | { |
---|
| 688 | if (abs(shutdown_lighting_value-c->ambient)<4) |
---|
| 689 | shutdown_lighting_value=c->ambient; |
---|
| 690 | else |
---|
| 691 | if (shutdown_lighting_value<c->ambient) |
---|
| 692 | shutdown_lighting_value+=4; |
---|
| 693 | else if (shutdown_lighting_value>c->ambient) |
---|
| 694 | shutdown_lighting_value-=4; |
---|
| 695 | } else shutdown_lighting=0; // back to normal |
---|
| 696 | } |
---|
| 697 | |
---|
| 698 | if (smallest) |
---|
| 699 | c->configure_for_area(smallest); |
---|
| 700 | |
---|
| 701 | |
---|
| 702 | o->move(c->x_suggestion,c->y_suggestion,c->b1_suggestion|(c->b2_suggestion<<1)| |
---|
| 703 | (c->b3_suggestion<<2)); |
---|
| 704 | |
---|
| 705 | if (o->otype!=current_start_type) |
---|
| 706 | { |
---|
[16] | 707 | int32_t fmp=o->fmp(); |
---|
[2] | 708 | int reduce=figures[o->otype]->morph_power; |
---|
| 709 | if (reduce) |
---|
| 710 | { |
---|
| 711 | fmp-=reduce; |
---|
| 712 | o->add_power(fmp>>16); |
---|
| 713 | o->set_fmp(fmp&0xffff); |
---|
| 714 | if (o->mp()<=0) |
---|
| 715 | o->morph_into(current_start_type,NULL,-1,9); |
---|
| 716 | } |
---|
| 717 | } |
---|
| 718 | |
---|
| 719 | l=o; |
---|
| 720 | o=o->next_active; |
---|
| 721 | } |
---|
| 722 | else if (!o->decide()) // if object returns 0, delete it... I don't like 0's :) |
---|
| 723 | { |
---|
| 724 | game_object *p=o; |
---|
| 725 | o=o->next_active; |
---|
| 726 | delete_object(p); |
---|
| 727 | cur=NULL; |
---|
| 728 | } else |
---|
| 729 | { |
---|
| 730 | o=o->next_active; |
---|
| 731 | l=o; |
---|
| 732 | } |
---|
| 733 | } else |
---|
| 734 | { |
---|
| 735 | o=o->next_active; |
---|
| 736 | l=o; |
---|
| 737 | } |
---|
| 738 | |
---|
| 739 | clear_tmp(); |
---|
| 740 | |
---|
| 741 | if (cur) |
---|
| 742 | { |
---|
| 743 | point_list *p=cur->current_figure()->hit; // see if this character is on an attack frame |
---|
| 744 | if (p && p->tot) |
---|
| 745 | add_attacker(cur); // if so add him to attack list for later collision detect |
---|
| 746 | |
---|
| 747 | if (cur->hurtable()) // add to target list if is hurtable |
---|
| 748 | add_target(cur); |
---|
| 749 | |
---|
| 750 | } |
---|
| 751 | |
---|
| 752 | } |
---|
| 753 | tick_panims(); |
---|
| 754 | |
---|
| 755 | check_collisions(); |
---|
| 756 | // wall_push(); |
---|
| 757 | |
---|
| 758 | set_tick_counter(tick_counter()+1); |
---|
| 759 | |
---|
| 760 | if (sshot_fcount!=-1) |
---|
| 761 | { |
---|
| 762 | sshot_fcount++; |
---|
| 763 | if ((sshot_fcount%70)==0) |
---|
| 764 | { |
---|
| 765 | char name[100]; |
---|
| 766 | sprintf(name,"shot%04d.pcx",screen_shot_on++); |
---|
| 767 | write_PCX(screen,pal,name); |
---|
| 768 | } |
---|
| 769 | } |
---|
| 770 | |
---|
| 771 | return ret; |
---|
| 772 | } |
---|
| 773 | |
---|
[17] | 774 | void level::set_tick_counter(uint32_t x) |
---|
[2] | 775 | { |
---|
| 776 | ctick=x; |
---|
| 777 | } |
---|
| 778 | |
---|
| 779 | void level::draw_areas(view *v) |
---|
| 780 | { |
---|
[16] | 781 | int32_t sx1,sy1,sx2,sy2; |
---|
[2] | 782 | area_controller *a=area_list; |
---|
| 783 | for (;a;a=a->next) |
---|
| 784 | { |
---|
| 785 | int c1,c2; |
---|
| 786 | if (a->active) |
---|
| 787 | { |
---|
| 788 | c1=morph_sel_frame_color; |
---|
[106] | 789 | c2=wm->bright_color(); |
---|
[2] | 790 | } else |
---|
| 791 | { |
---|
| 792 | c2=morph_sel_frame_color; |
---|
[106] | 793 | c1=wm->bright_color(); |
---|
[2] | 794 | } |
---|
| 795 | |
---|
| 796 | the_game->game_to_mouse(a->x,a->y,v,sx1,sy1); |
---|
| 797 | the_game->game_to_mouse(a->x+a->w,a->y+a->h,v,sx2,sy2); |
---|
| 798 | screen->rectangle(sx1,sy1,sx2,sy2,c1); |
---|
| 799 | screen->bar(sx1-1,sy1-1,sx1+1,sy1+1,c2); |
---|
| 800 | screen->bar(sx2-1,sy2-1,sx2+1,sy2+1,c2); |
---|
| 801 | } |
---|
| 802 | } |
---|
| 803 | |
---|
| 804 | void level::draw_objects(view *v) |
---|
| 805 | { |
---|
| 806 | current_view=v; |
---|
| 807 | game_object *o=first_active; |
---|
| 808 | if (dev&MAP_MODE) |
---|
| 809 | { |
---|
| 810 | for (;o;o=o->next_active) |
---|
| 811 | o->map_draw(); |
---|
| 812 | } else |
---|
| 813 | { |
---|
| 814 | for (;o;o=o->next_active) |
---|
| 815 | o->draw(); |
---|
| 816 | } |
---|
| 817 | |
---|
| 818 | clear_tmp(); |
---|
| 819 | } |
---|
| 820 | |
---|
[16] | 821 | void calc_bgsize(uint16_t fgw, uint16_t fgh, uint16_t &bgw, uint16_t &bgh) |
---|
[2] | 822 | { |
---|
| 823 | bgw=fgw/ASPECT+8; |
---|
| 824 | bgh=fgh/ASPECT+8; |
---|
| 825 | } |
---|
| 826 | |
---|
| 827 | |
---|
| 828 | void level::set_size(int w, int h) |
---|
| 829 | { |
---|
| 830 | if (w*h>200000) |
---|
| 831 | { |
---|
| 832 | the_game->show_help(symbol_str("too_big")); |
---|
| 833 | return ; |
---|
| 834 | } |
---|
| 835 | |
---|
[16] | 836 | uint16_t *new_fg,*new_bg; |
---|
| 837 | new_fg=(uint16_t *)jmalloc(w*h*sizeof(int16_t),"Map fg : resized"); |
---|
| 838 | memset(new_fg,0,w*h*sizeof(int16_t)); |
---|
[2] | 839 | |
---|
| 840 | int x,y,miny=(h<fg_height)? h : fg_height,minx=(w<fg_width)? w : fg_width; |
---|
| 841 | |
---|
[16] | 842 | uint16_t nbw,nbh; |
---|
[2] | 843 | calc_bgsize(w,h,nbw,nbh); |
---|
| 844 | |
---|
[16] | 845 | new_bg=(uint16_t *)jmalloc((int)nbw*(int)nbh*sizeof(int16_t),"map bg : resized"); |
---|
| 846 | memset(new_bg,0,(int)nbw*(int)nbh*sizeof(int16_t)); |
---|
[2] | 847 | |
---|
| 848 | for (y=0;y<miny;y++) |
---|
| 849 | for (x=0;x<minx;x++) |
---|
| 850 | new_fg[x+y*w]=get_fg(x,y); |
---|
| 851 | |
---|
| 852 | miny=(nbh<bg_height) ? nbh : bg_height; |
---|
| 853 | minx=(nbw<bg_width) ? nbw : bg_width; |
---|
| 854 | |
---|
| 855 | for (y=0;y<miny;y++) |
---|
| 856 | for (x=0;x<minx;x++) |
---|
| 857 | new_bg[x+y*nbw]=get_bg(x,y); |
---|
| 858 | |
---|
| 859 | jfree(map_fg); |
---|
| 860 | jfree(map_bg); |
---|
| 861 | map_fg=new_fg; |
---|
| 862 | map_bg=new_bg; |
---|
| 863 | fg_width=w; |
---|
| 864 | fg_height=h; |
---|
| 865 | bg_height=nbh; |
---|
| 866 | bg_width=nbw; |
---|
| 867 | |
---|
| 868 | char msg[80]; |
---|
| 869 | sprintf(msg,"Level %s size now %d %d\n",name(),foreground_width(),foreground_height()); |
---|
| 870 | the_game->show_help(msg); |
---|
| 871 | } |
---|
| 872 | |
---|
| 873 | |
---|
| 874 | int locate_var(bFILE *fp, spec_directory *sd, char *str, int size) |
---|
| 875 | { |
---|
| 876 | spec_entry *se=sd->find(str); |
---|
| 877 | if (se) |
---|
| 878 | { |
---|
| 879 | fp->seek(se->offset,0); |
---|
[17] | 880 | if (RC_type_size(fp->read_uint8())!=size) |
---|
[2] | 881 | return 0; |
---|
| 882 | else return 1; |
---|
| 883 | } |
---|
| 884 | return 0; |
---|
| 885 | } |
---|
| 886 | |
---|
| 887 | |
---|
| 888 | // load objects assumes current objects have already been disposed of |
---|
| 889 | void level::old_load_objects(spec_directory *sd, bFILE *fp) |
---|
| 890 | { |
---|
| 891 | spec_entry *se=sd->find("objects"); |
---|
| 892 | total_objs=0; |
---|
| 893 | first=last=first_active=NULL; |
---|
| 894 | int i,j; |
---|
| 895 | if (se) |
---|
| 896 | { |
---|
| 897 | fp->seek(se->offset,0); |
---|
| 898 | /******************************* Read debug info ******************************/ |
---|
[17] | 899 | int16_t old_tot=fp->read_uint16(); |
---|
[16] | 900 | uint16_t *o_remap=(uint16_t *)jmalloc(old_tot*2,"obj remap array"); |
---|
[2] | 901 | char old_name[150]; |
---|
| 902 | for (i=0;i<old_tot;i++) |
---|
| 903 | { |
---|
[17] | 904 | fp->read(old_name,fp->read_uint8()); // read the name |
---|
[2] | 905 | for (o_remap[i]=0xffff,j=0;j<total_objects;j++) // check for matching current name |
---|
| 906 | { |
---|
| 907 | if (!strcmp(old_name,object_names[j])) |
---|
| 908 | o_remap[i]=j; |
---|
| 909 | } |
---|
| 910 | } |
---|
| 911 | |
---|
| 912 | |
---|
| 913 | /***************************** Read state names *********************************/ |
---|
[17] | 914 | int old_stot=fp->read_uint16(); |
---|
[2] | 915 | unsigned char *s_remap=(unsigned char *)jmalloc(old_stot,"state remap array"); |
---|
| 916 | for (i=0;i<old_stot;i++) |
---|
| 917 | { |
---|
[17] | 918 | fp->read(old_name,fp->read_uint8()); |
---|
[2] | 919 | s_remap[i]=stopped; // non exsitant states get mapped into stopped state |
---|
| 920 | for (j=0;j<MAX_STATE;j++) // see if old state exist now |
---|
| 921 | if (!strcmp(state_names[j],old_name)) |
---|
| 922 | s_remap[i]=j; |
---|
| 923 | } |
---|
[17] | 924 | total_objs=fp->read_uint32(); |
---|
[2] | 925 | |
---|
| 926 | se=sd->find("type"); |
---|
| 927 | if (se) |
---|
| 928 | { |
---|
| 929 | fp->seek(se->offset,0); |
---|
| 930 | last=NULL; |
---|
[18] | 931 | if (fp->read_uint8()==RC_16) // read type array, this should be type RC_16 |
---|
[2] | 932 | { |
---|
| 933 | for (i=0;i<total_objs;i++) |
---|
| 934 | { |
---|
[17] | 935 | uint16_t t=fp->read_uint16(); |
---|
[2] | 936 | game_object *p=new game_object(o_remap[t],1); |
---|
| 937 | clear_tmp(); |
---|
| 938 | if (!first) first=p; else last->next=p; |
---|
| 939 | last=p; p->next=NULL; |
---|
| 940 | } |
---|
| 941 | |
---|
| 942 | |
---|
| 943 | se=sd->find("state"); |
---|
| 944 | if (se) |
---|
| 945 | { |
---|
| 946 | fp->seek(se->offset,0); |
---|
[18] | 947 | if (fp->read_uint8()==RC_16) // read state array, this should be type RC_16 |
---|
[2] | 948 | { |
---|
| 949 | game_object *l=first; |
---|
| 950 | for (i=0;i<total_objs;i++,l=l->next) |
---|
| 951 | { |
---|
[17] | 952 | character_state s=(character_state)s_remap[fp->read_uint16()]; |
---|
[2] | 953 | if (l->otype!=0xffff) |
---|
| 954 | { |
---|
| 955 | if (l->has_sequence((character_state)s)) |
---|
| 956 | l->state=s; |
---|
| 957 | else l->state=stopped; |
---|
| 958 | l->current_frame=0; |
---|
| 959 | } |
---|
| 960 | } |
---|
| 961 | } |
---|
| 962 | } |
---|
| 963 | |
---|
| 964 | int frame_var=0; |
---|
| 965 | int i=0; |
---|
| 966 | for (;i<TOTAL_OBJECT_VARS;i++) |
---|
| 967 | if (!strcmp(object_descriptions[i].name,"cur_frame")) |
---|
| 968 | frame_var=i; |
---|
| 969 | |
---|
| 970 | int j=0; |
---|
| 971 | for (;j<default_simple.total_vars();j++) |
---|
| 972 | { |
---|
| 973 | spec_entry *se=sd->find(object_descriptions[j].name); |
---|
| 974 | if (se) |
---|
| 975 | { |
---|
| 976 | fp->seek(se->offset,0); |
---|
| 977 | int t=object_descriptions[j].type; |
---|
[17] | 978 | if (fp->read_uint8()!=t) |
---|
[2] | 979 | dprintf("Warning : load level -> var '%s' size changed\n"); |
---|
| 980 | else |
---|
| 981 | { |
---|
| 982 | game_object *f=first; |
---|
| 983 | for (;f;f=f->next) |
---|
| 984 | { |
---|
| 985 | switch (t) |
---|
| 986 | { |
---|
[18] | 987 | case RC_8 : f->set_var(j,fp->read_uint8()); break; |
---|
| 988 | case RC_16 : f->set_var(j,fp->read_uint16()); break; |
---|
| 989 | case RC_32 : f->set_var(j,fp->read_uint32()); break; |
---|
[2] | 990 | } |
---|
| 991 | |
---|
| 992 | // check to make sure the frame number is not out of bounds from the time |
---|
| 993 | // it was last saved |
---|
| 994 | if (j==frame_var) |
---|
| 995 | { |
---|
| 996 | if (f->otype!=0xffff && f->current_frame>= |
---|
| 997 | figures[f->otype]->get_sequence(f->state)->length()) |
---|
| 998 | f->current_frame=0; |
---|
| 999 | } |
---|
| 1000 | } |
---|
| 1001 | } |
---|
| 1002 | } else dprintf("Warning : load level -> no previous var %s\n",default_simple.var_name(j)); |
---|
| 1003 | } |
---|
| 1004 | } |
---|
| 1005 | } |
---|
| 1006 | |
---|
| 1007 | |
---|
| 1008 | |
---|
| 1009 | jfree(o_remap); |
---|
| 1010 | jfree(s_remap); |
---|
| 1011 | } |
---|
| 1012 | |
---|
| 1013 | } |
---|
| 1014 | |
---|
| 1015 | |
---|
| 1016 | // load objects assumes current objects have already been disposed of |
---|
| 1017 | void level::load_objects(spec_directory *sd, bFILE *fp) |
---|
| 1018 | { |
---|
| 1019 | spec_entry *se=sd->find("object_descripitions"); |
---|
| 1020 | total_objs=0; |
---|
| 1021 | first=last=first_active=NULL; |
---|
| 1022 | int i,j; |
---|
| 1023 | if (!se) |
---|
| 1024 | { |
---|
| 1025 | old_load_objects(sd,fp); |
---|
| 1026 | return ; |
---|
| 1027 | } |
---|
| 1028 | else if (se) |
---|
| 1029 | { |
---|
| 1030 | fp->seek(se->offset,0); |
---|
[17] | 1031 | int16_t old_tot=fp->read_uint16(); |
---|
[2] | 1032 | se=sd->find("describe_names"); |
---|
| 1033 | if (!se || !old_tot) |
---|
| 1034 | return ; |
---|
| 1035 | |
---|
[16] | 1036 | uint16_t *o_remap=(uint16_t *)jmalloc(old_tot*2,"obj remap array"); |
---|
| 1037 | uint16_t *o_backmap=(uint16_t *)jmalloc(total_objects*2,"obj remap array"); |
---|
[2] | 1038 | memset(o_backmap,0xff,total_objects*2); |
---|
| 1039 | char old_name[150]; |
---|
| 1040 | for (i=0;i<old_tot;i++) |
---|
| 1041 | { |
---|
[17] | 1042 | fp->read(old_name,fp->read_uint8()); // read the name |
---|
[2] | 1043 | for (o_remap[i]=0xffff,j=0;j<total_objects;j++) // check for matching current name |
---|
| 1044 | { |
---|
| 1045 | if (!strcmp(old_name,object_names[j])) |
---|
| 1046 | { |
---|
| 1047 | o_remap[i]=j; |
---|
| 1048 | o_backmap[j]=i; |
---|
| 1049 | } |
---|
| 1050 | } |
---|
| 1051 | } |
---|
| 1052 | |
---|
| 1053 | se=sd->find("describe_states"); |
---|
| 1054 | if (!se) { jfree(o_remap); jfree(o_backmap); return ; } |
---|
[16] | 1055 | int16_t **s_remap=(int16_t **)jmalloc(old_tot*sizeof(int16_t *),"big state remap array"); |
---|
| 1056 | int16_t *s_remap_totals=(int16_t *)jmalloc(old_tot*sizeof(int16_t),"big state rmp totals"); |
---|
[2] | 1057 | fp->seek(se->offset,0); |
---|
| 1058 | int i=0; |
---|
| 1059 | for (;i<old_tot;i++) |
---|
| 1060 | { |
---|
[17] | 1061 | int16_t t=fp->read_uint16(); |
---|
[2] | 1062 | s_remap_totals[i]=t; |
---|
| 1063 | if (t) |
---|
| 1064 | { |
---|
[16] | 1065 | s_remap[i]=(int16_t *)jmalloc(t*sizeof(int16_t),"state remap"); |
---|
[2] | 1066 | int j=0; |
---|
| 1067 | for (;j<t;j++) |
---|
| 1068 | *(s_remap[i]+j)=stopped; // if no remap found, then go to stopped state |
---|
| 1069 | } |
---|
| 1070 | else s_remap[i]=0; |
---|
| 1071 | |
---|
| 1072 | int j=0; |
---|
| 1073 | for (;j<t;j++) |
---|
| 1074 | { |
---|
[17] | 1075 | fp->read(old_name,fp->read_uint8()); |
---|
[2] | 1076 | int new_type=o_remap[i]; |
---|
| 1077 | if (new_type<total_objects) // make sure old object still exsist |
---|
| 1078 | { |
---|
| 1079 | int k=0; |
---|
| 1080 | for (;k<figures[new_type]->ts;k++) |
---|
| 1081 | { |
---|
| 1082 | if (figures[new_type]->seq[k] && |
---|
| 1083 | !strcmp(lstring_value(symbol_name(figures[new_type]->seq_syms[k])),old_name)) |
---|
| 1084 | *(s_remap[i]+j)=k; |
---|
| 1085 | } |
---|
| 1086 | } |
---|
| 1087 | } |
---|
| 1088 | } |
---|
| 1089 | |
---|
[16] | 1090 | int16_t **v_remap=NULL; |
---|
| 1091 | int16_t *v_remap_totals=NULL; |
---|
[2] | 1092 | int load_vars=1; |
---|
| 1093 | se=sd->find("describe_lvars"); |
---|
| 1094 | if (se) |
---|
| 1095 | { |
---|
[16] | 1096 | v_remap=(int16_t **)jmalloc(old_tot*sizeof(int16_t *),"big var remap array"); |
---|
| 1097 | v_remap_totals=(int16_t *)jmalloc(old_tot*sizeof(int16_t),"big var rmp totals"); |
---|
[2] | 1098 | |
---|
| 1099 | fp->seek(se->offset,0); |
---|
| 1100 | int i=0; |
---|
| 1101 | for (;i<old_tot;i++) |
---|
| 1102 | { |
---|
[17] | 1103 | int16_t t=fp->read_uint16(); |
---|
[2] | 1104 | v_remap_totals[i]=t; |
---|
| 1105 | if (t) |
---|
| 1106 | { |
---|
[16] | 1107 | v_remap[i]=(int16_t *)jmalloc(t*sizeof(int16_t),"var remap"); |
---|
| 1108 | memset(v_remap[i],0xff,t*sizeof(int16_t)); |
---|
[2] | 1109 | } else { v_remap[i]=NULL; } |
---|
| 1110 | int j=0; |
---|
| 1111 | for (;j<t;j++) |
---|
| 1112 | { |
---|
[17] | 1113 | fp->read(old_name,fp->read_uint8()); |
---|
[2] | 1114 | int new_type=o_remap[i]; |
---|
| 1115 | if (new_type!=0xffff) // make sure old object still exsist |
---|
| 1116 | { |
---|
| 1117 | int k=0; |
---|
| 1118 | for (;k<figures[new_type]->tiv;k++) |
---|
| 1119 | { |
---|
| 1120 | if (figures[new_type]->vars[k]) |
---|
| 1121 | { |
---|
| 1122 | if (!strcmp(lstring_value(symbol_name(figures[new_type]->vars[k])),old_name)) |
---|
| 1123 | *(v_remap[i]+j)=figures[new_type]->var_index[k]; |
---|
| 1124 | } |
---|
| 1125 | } |
---|
| 1126 | } |
---|
| 1127 | } |
---|
| 1128 | } |
---|
| 1129 | load_vars=1; |
---|
| 1130 | } |
---|
| 1131 | |
---|
| 1132 | se=sd->find("object_list"); |
---|
| 1133 | if (se) |
---|
| 1134 | { |
---|
[17] | 1135 | total_objs=fp->read_uint32(); |
---|
[2] | 1136 | |
---|
| 1137 | se=sd->find("type"); |
---|
| 1138 | if (se) |
---|
| 1139 | { |
---|
| 1140 | fp->seek(se->offset,0); |
---|
| 1141 | last=NULL; |
---|
[18] | 1142 | if (fp->read_uint8()==RC_16) // read type array, this should be type RC_16 |
---|
[2] | 1143 | { |
---|
| 1144 | int i=0; |
---|
| 1145 | for (;i<total_objs;i++) |
---|
| 1146 | { |
---|
[17] | 1147 | uint16_t t=fp->read_uint16(); |
---|
[2] | 1148 | game_object *p=new game_object(o_remap[t],1); |
---|
| 1149 | clear_tmp(); |
---|
| 1150 | if (!first) first=p; else last->next=p; |
---|
| 1151 | last=p; p->next=NULL; |
---|
| 1152 | } |
---|
| 1153 | |
---|
| 1154 | se=sd->find("state"); |
---|
| 1155 | if (se) |
---|
| 1156 | { |
---|
| 1157 | fp->seek(se->offset,0); |
---|
[18] | 1158 | if (fp->read_uint8()==RC_16) // read state array, this should be type RC_16 |
---|
[2] | 1159 | { |
---|
| 1160 | game_object *l=first; |
---|
| 1161 | for (i=0;i<total_objs;i++,l=l->next) |
---|
| 1162 | { |
---|
[17] | 1163 | int st=fp->read_uint16(); |
---|
[2] | 1164 | if (l->otype==0xffff) |
---|
| 1165 | l->state=stopped; |
---|
| 1166 | else |
---|
| 1167 | { |
---|
| 1168 | character_state s=(character_state)(*(s_remap[o_backmap[l->otype]]+st)); |
---|
| 1169 | if (l->has_sequence((character_state)s)) |
---|
| 1170 | l->state=s; |
---|
| 1171 | else l->state=stopped; |
---|
| 1172 | l->current_frame=0; |
---|
| 1173 | } |
---|
| 1174 | } |
---|
| 1175 | } |
---|
| 1176 | } |
---|
| 1177 | |
---|
| 1178 | se=sd->find("lvars"); |
---|
| 1179 | if (se && load_vars) |
---|
| 1180 | { |
---|
| 1181 | fp->seek(se->offset,0); |
---|
| 1182 | int abort=0; |
---|
| 1183 | game_object *o=first; |
---|
| 1184 | for (;o && !abort;o=o->next) |
---|
| 1185 | { |
---|
[17] | 1186 | int16_t ot=fp->read_uint16(); |
---|
[2] | 1187 | int k=0; |
---|
| 1188 | for (;k<ot;k++) |
---|
| 1189 | { |
---|
[18] | 1190 | if (fp->read_uint8()!=RC_32) abort=1; |
---|
[2] | 1191 | else |
---|
| 1192 | { |
---|
[17] | 1193 | int32_t v=fp->read_uint32(); |
---|
[2] | 1194 | if (o->otype!=0xffff) // non-exstant object |
---|
| 1195 | { |
---|
| 1196 | int remap=*(v_remap[o_backmap[o->otype]]+k); |
---|
| 1197 | if (remap!=-1 && figures[o->otype]->tiv>=k) |
---|
| 1198 | { |
---|
| 1199 | o->lvars[remap]=v; |
---|
| 1200 | } |
---|
| 1201 | } |
---|
| 1202 | } |
---|
| 1203 | } |
---|
| 1204 | } |
---|
| 1205 | } |
---|
| 1206 | |
---|
| 1207 | int frame_var=0; |
---|
| 1208 | for (i=0;i<TOTAL_OBJECT_VARS;i++) |
---|
| 1209 | if (!strcmp(object_descriptions[i].name,"cur_frame")) |
---|
| 1210 | frame_var=i; |
---|
| 1211 | |
---|
| 1212 | |
---|
| 1213 | int j=0; |
---|
| 1214 | for (;j<default_simple.total_vars();j++) |
---|
| 1215 | { |
---|
| 1216 | spec_entry *se=sd->find(object_descriptions[j].name); |
---|
| 1217 | if (se) |
---|
| 1218 | { |
---|
| 1219 | fp->seek(se->offset,0); |
---|
| 1220 | int t=object_descriptions[j].type; |
---|
[17] | 1221 | if (fp->read_uint8()!=t) |
---|
[2] | 1222 | dprintf("Warning : load level -> var '%s' size changed\n"); |
---|
| 1223 | else |
---|
| 1224 | { |
---|
| 1225 | game_object *f=first; |
---|
| 1226 | for (;f;f=f->next) |
---|
| 1227 | { |
---|
| 1228 | switch (t) |
---|
| 1229 | { |
---|
[18] | 1230 | case RC_8 : |
---|
[17] | 1231 | { f->set_var(j,fp->read_uint8()); } break; |
---|
[18] | 1232 | case RC_16 : |
---|
[17] | 1233 | { f->set_var(j,fp->read_uint16()); } break; |
---|
[18] | 1234 | case RC_32 : |
---|
[17] | 1235 | { f->set_var(j,fp->read_uint32()); } break; |
---|
[2] | 1236 | } |
---|
| 1237 | |
---|
| 1238 | // check to make sure the frame number is not out of bounds from the time |
---|
| 1239 | // it was last saved |
---|
| 1240 | if (j==frame_var) |
---|
| 1241 | { |
---|
| 1242 | if (f->otype!=0xffff && f->current_frame>= |
---|
| 1243 | figures[f->otype]->get_sequence(f->state)->length()) |
---|
| 1244 | f->current_frame=0; |
---|
| 1245 | } |
---|
| 1246 | } |
---|
| 1247 | } |
---|
| 1248 | } else dprintf("Warning : load level -> no previous var %s\n",default_simple.var_name(j)); |
---|
| 1249 | } |
---|
| 1250 | } |
---|
| 1251 | } |
---|
| 1252 | } |
---|
| 1253 | |
---|
| 1254 | int k=0; |
---|
| 1255 | for (;k<old_tot;k++) |
---|
| 1256 | { |
---|
| 1257 | if (s_remap_totals[k]) |
---|
| 1258 | jfree(s_remap[k]); |
---|
| 1259 | } |
---|
| 1260 | |
---|
| 1261 | int l=0; |
---|
| 1262 | for (;l<old_tot;l++) |
---|
| 1263 | { |
---|
| 1264 | if (v_remap_totals[l]) |
---|
| 1265 | jfree(v_remap[l]); |
---|
| 1266 | } |
---|
| 1267 | jfree(v_remap_totals); |
---|
| 1268 | jfree(s_remap_totals); |
---|
| 1269 | jfree(o_remap); |
---|
| 1270 | jfree(o_backmap); |
---|
| 1271 | jfree(s_remap); |
---|
| 1272 | jfree(v_remap); |
---|
| 1273 | } |
---|
| 1274 | |
---|
| 1275 | } |
---|
| 1276 | |
---|
[39] | 1277 | level::level(spec_directory *sd, bFILE *fp, char const *lev_name) |
---|
[2] | 1278 | { |
---|
| 1279 | spec_entry *e; |
---|
| 1280 | area_list=NULL; |
---|
| 1281 | |
---|
| 1282 | attack_list=NULL; |
---|
| 1283 | attack_list_size=attack_total=0; |
---|
| 1284 | |
---|
| 1285 | target_list=NULL; |
---|
| 1286 | target_list_size=target_total=0; |
---|
| 1287 | |
---|
| 1288 | block_list=NULL; |
---|
| 1289 | block_list_size=block_total=0; |
---|
| 1290 | |
---|
| 1291 | all_block_list=NULL; |
---|
| 1292 | all_block_list_size=all_block_total=0; |
---|
| 1293 | first_name=NULL; |
---|
| 1294 | |
---|
| 1295 | the_game->need_refresh(); |
---|
| 1296 | |
---|
| 1297 | char cmd[100]; |
---|
| 1298 | sprintf(cmd,symbol_str("loading"),lev_name); |
---|
| 1299 | stack_stat stat(cmd); |
---|
| 1300 | Name=strcpy((char *)jmalloc(strlen(lev_name)+1,"lev name"),lev_name); |
---|
| 1301 | |
---|
| 1302 | e=sd->find("first name"); |
---|
| 1303 | if (e) |
---|
| 1304 | { |
---|
| 1305 | fp->seek(e->offset,0); |
---|
[17] | 1306 | int len=fp->read_uint8(); // read the length of the string |
---|
[2] | 1307 | first_name=(char *)jmalloc(len,"level first name"); |
---|
| 1308 | fp->read(first_name,len); // read the string |
---|
| 1309 | } else |
---|
| 1310 | { |
---|
| 1311 | first_name=(char *)jmalloc(strlen(Name)+1,"level first name"); |
---|
| 1312 | strcpy(first_name,Name); |
---|
| 1313 | } |
---|
| 1314 | |
---|
| 1315 | e=sd->find("fgmap"); |
---|
| 1316 | int no_fg=0,no_bg=0; |
---|
| 1317 | |
---|
| 1318 | if (e) |
---|
| 1319 | { |
---|
| 1320 | fp->seek(e->offset,0); |
---|
[17] | 1321 | fg_width=fp->read_uint32(); |
---|
| 1322 | fg_height=fp->read_uint32(); |
---|
[16] | 1323 | map_fg=(uint16_t *)jmalloc(2*fg_width*fg_height,"Map fg : loaded"); |
---|
[2] | 1324 | fp->read((char *)map_fg,2*fg_width*fg_height); |
---|
| 1325 | int t=fg_width*fg_height; |
---|
[16] | 1326 | uint16_t *map=map_fg; |
---|
[2] | 1327 | while (t) { *map=lstl(*map); map++; t--; } |
---|
| 1328 | } else |
---|
| 1329 | { |
---|
| 1330 | the_game->show_help("Warning foreground map missing"); |
---|
| 1331 | no_fg=1; |
---|
| 1332 | } |
---|
| 1333 | stat_man->update(5); |
---|
| 1334 | |
---|
| 1335 | e=sd->find("bgmap"); |
---|
| 1336 | if (e) |
---|
| 1337 | { |
---|
| 1338 | fp->seek(e->offset,0); |
---|
[17] | 1339 | bg_width=fp->read_uint32(); |
---|
| 1340 | bg_height=fp->read_uint32(); |
---|
[16] | 1341 | map_bg=(uint16_t *)jmalloc(2*bg_width*bg_height,"Map bg : loaded"); |
---|
[2] | 1342 | fp->read((char *)map_bg,2*bg_width*bg_height); |
---|
| 1343 | int t=bg_width*bg_height; |
---|
[16] | 1344 | uint16_t *map=map_bg; |
---|
[2] | 1345 | while (t) { *map=lstl(*map); map++; t--; } |
---|
| 1346 | } else |
---|
| 1347 | { |
---|
| 1348 | the_game->show_help("Warning background map missing"); |
---|
| 1349 | no_bg=1; |
---|
| 1350 | } |
---|
| 1351 | |
---|
| 1352 | if (no_fg && !no_bg) |
---|
| 1353 | { |
---|
| 1354 | fg_width=bg_width; |
---|
| 1355 | fg_height=bg_height; |
---|
[16] | 1356 | map_fg=(uint16_t *)jmalloc(2*fg_width*fg_height,"Map fg : loaded"); |
---|
[2] | 1357 | memset(map_fg,0,2*fg_width*fg_height); |
---|
| 1358 | } |
---|
| 1359 | |
---|
| 1360 | if (no_bg) |
---|
| 1361 | { |
---|
| 1362 | bg_width=fg_width/8+8; |
---|
| 1363 | bg_height=fg_height/8+8; |
---|
[16] | 1364 | map_bg=(uint16_t *)jmalloc(2*bg_width*bg_height,"Map bg : loaded"); |
---|
[2] | 1365 | memset(map_bg,0,2*bg_width*bg_height); |
---|
| 1366 | } |
---|
| 1367 | stat_man->update(10); |
---|
| 1368 | |
---|
| 1369 | /***************** Check map for non exsistant tiles **************************/ |
---|
[16] | 1370 | int32_t i,w; |
---|
| 1371 | uint16_t *m; |
---|
[2] | 1372 | spec_entry *load_all=sd->find("player_info"); |
---|
| 1373 | for (i=0,w=fg_width*fg_height,m=map_fg;i<w;i++,m++) |
---|
| 1374 | { |
---|
| 1375 | if (!load_all) |
---|
| 1376 | (*m)=(*m)&(~0x8000); // clear the has-seen bit on the tile |
---|
| 1377 | |
---|
| 1378 | if (fgvalue(*m)>=nforetiles || foretiles[fgvalue(*m)]<0) |
---|
| 1379 | *m=0; |
---|
| 1380 | } |
---|
| 1381 | |
---|
| 1382 | for (i=0,w=bg_width*bg_height,m=map_bg;i<w;i++,m++) |
---|
| 1383 | { |
---|
| 1384 | if ( (bgvalue(*m)>=nbacktiles) || backtiles[bgvalue(*m)]<0) |
---|
| 1385 | *m=0; |
---|
| 1386 | } |
---|
| 1387 | |
---|
| 1388 | load_options(sd,fp); |
---|
| 1389 | stat_man->update(15); |
---|
| 1390 | |
---|
| 1391 | // first=first_active=last=NULL; |
---|
| 1392 | load_objects(sd,fp); |
---|
| 1393 | stat_man->update(25); |
---|
| 1394 | |
---|
| 1395 | object_node *players,*objs; |
---|
| 1396 | players=make_player_onodes(); |
---|
| 1397 | objs=make_not_list(players); |
---|
| 1398 | |
---|
| 1399 | |
---|
| 1400 | |
---|
| 1401 | read_lights(sd,fp,lev_name); |
---|
| 1402 | load_links(fp,sd,objs,players); |
---|
| 1403 | int players_got_loaded=load_player_info(fp,sd,objs); |
---|
| 1404 | |
---|
| 1405 | |
---|
| 1406 | game_object *l=first; |
---|
| 1407 | for (;l;) |
---|
| 1408 | { |
---|
| 1409 | game_object *p=l; |
---|
| 1410 | l=l->next; |
---|
| 1411 | if (p->otype==0xffff || p->x<0 || p->y<0) |
---|
| 1412 | delete_object(p); |
---|
| 1413 | } |
---|
| 1414 | |
---|
| 1415 | load_cache_info(sd,fp); |
---|
| 1416 | |
---|
| 1417 | if (!players_got_loaded) |
---|
| 1418 | { |
---|
| 1419 | level *old=current_level; |
---|
| 1420 | current_level=this; |
---|
| 1421 | |
---|
| 1422 | object_node *list=NULL; |
---|
| 1423 | list=make_not_list(list); // create a list of the object list in case objects change positions |
---|
| 1424 | |
---|
| 1425 | object_node *ln=list; |
---|
| 1426 | for (;ln;ln=ln->next) |
---|
| 1427 | ln->me->reload_notify(); |
---|
| 1428 | delete_object_list(list); |
---|
| 1429 | |
---|
| 1430 | current_level=old; |
---|
| 1431 | |
---|
| 1432 | insert_players(); |
---|
| 1433 | } |
---|
| 1434 | |
---|
| 1435 | delete_object_list(players); |
---|
| 1436 | delete_object_list(objs); |
---|
| 1437 | |
---|
| 1438 | } |
---|
| 1439 | |
---|
| 1440 | |
---|
| 1441 | /* |
---|
| 1442 | [object_descriptions] 2 total_type |
---|
| 1443 | for(1..total_types) |
---|
| 1444 | { |
---|
| 1445 | ["object_names"] 1,(name) |
---|
| 1446 | |
---|
| 1447 | ["object_states"] 2(total),<2=number,1,name> |
---|
| 1448 | |
---|
| 1449 | ["object_lvars"] 2(total),<1(type),1,name> |
---|
| 1450 | } |
---|
| 1451 | |
---|
| 1452 | [object_list] |
---|
| 1453 | 4 total_objects |
---|
| 1454 | for(1..total_objects) |
---|
| 1455 | { |
---|
| 1456 | ["type"] |
---|
| 1457 | ["state"] |
---|
| 1458 | ["lvars"] |
---|
| 1459 | ... |
---|
| 1460 | } |
---|
| 1461 | |
---|
| 1462 | */ |
---|
| 1463 | |
---|
| 1464 | |
---|
| 1465 | void get_prof_assoc_filename(char *filename, char *prof_filename) |
---|
| 1466 | { |
---|
| 1467 | char *s1,*s2,*dot=NULL; |
---|
| 1468 | for (s1=filename,s2=prof_filename,dot=NULL;*s1;s1++,s2++) |
---|
| 1469 | { |
---|
| 1470 | *s2=*s1; |
---|
| 1471 | if (*s1=='.') dot=s2; |
---|
| 1472 | } |
---|
| 1473 | if (dot) s2=dot+1; |
---|
| 1474 | |
---|
| 1475 | *(s2++)='c'; |
---|
| 1476 | *(s2++)='p'; |
---|
| 1477 | *(s2++)='f'; |
---|
| 1478 | *s2=0; |
---|
| 1479 | } |
---|
| 1480 | |
---|
| 1481 | void level::level_loaded_notify() |
---|
| 1482 | { |
---|
| 1483 | char *n; |
---|
| 1484 | if (first_name) |
---|
| 1485 | n=first_name; |
---|
| 1486 | else |
---|
| 1487 | n=name(); |
---|
| 1488 | if (strstr(n,"levels/level")) |
---|
| 1489 | { |
---|
| 1490 | char nm[100]; |
---|
| 1491 | sprintf(nm,"music/abuse%c%c.hmi",n[12],n[13]); |
---|
| 1492 | bFILE *fp=open_file(nm,"rb"); |
---|
| 1493 | if (fp->open_failure()) |
---|
| 1494 | { |
---|
| 1495 | delete fp; |
---|
| 1496 | } |
---|
| 1497 | else |
---|
| 1498 | { |
---|
| 1499 | if (current_song) { current_song->stop(); delete current_song; } |
---|
| 1500 | |
---|
| 1501 | delete fp; |
---|
| 1502 | current_song=new song(nm); |
---|
| 1503 | current_song->play(music_volume); |
---|
| 1504 | } |
---|
| 1505 | } |
---|
| 1506 | |
---|
| 1507 | /* if (DEFINEDP(symbol_function(l_level_loaded))) |
---|
| 1508 | { |
---|
| 1509 | int sp=current_space; |
---|
| 1510 | current_space=PERM_SPACE; |
---|
| 1511 | |
---|
| 1512 | void *arg_list=NULL; |
---|
| 1513 | p_ref r1(arg_list); |
---|
| 1514 | push_onto_list(new_lisp_string(n),arg_list); |
---|
| 1515 | eval_function((lisp_symbol *)l_level_loaded,arg_list); |
---|
| 1516 | |
---|
| 1517 | current_space=sp; |
---|
| 1518 | } */ |
---|
| 1519 | } |
---|
| 1520 | |
---|
| 1521 | |
---|
| 1522 | bFILE *level::create_dir(char *filename, int save_all, |
---|
| 1523 | object_node *save_list, object_node *exclude_list) |
---|
| 1524 | { |
---|
| 1525 | spec_directory sd; |
---|
| 1526 | sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"Copyright 1995 Crack dot Com, All Rights reserved",NULL,0,0)); |
---|
| 1527 | if (first_name) |
---|
| 1528 | sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"first name",NULL,strlen(first_name)+2,0)); |
---|
| 1529 | |
---|
| 1530 | |
---|
| 1531 | |
---|
| 1532 | sd.add_by_hand(new spec_entry(SPEC_GRUE_FGMAP,"fgmap",NULL,4+4+fg_width*fg_height*2,0)); |
---|
| 1533 | sd.add_by_hand(new spec_entry(SPEC_GRUE_BGMAP,"bgmap",NULL,4+4+bg_width*bg_height*2,0)); |
---|
| 1534 | sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"bg_scroll_rate",NULL,1+4*4,0)); |
---|
| 1535 | |
---|
| 1536 | int ta=0; |
---|
| 1537 | area_controller *a=area_list; |
---|
| 1538 | for (;a;a=a->next) ta++; |
---|
| 1539 | |
---|
| 1540 | sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"area_list.v1",NULL,1+ta*(4*11)+4,0)); |
---|
| 1541 | |
---|
| 1542 | sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"tick_counter",NULL,1+4,0)); |
---|
| 1543 | |
---|
| 1544 | |
---|
| 1545 | |
---|
| 1546 | // how many object types are we goint to save, use a short to specify how many |
---|
| 1547 | sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"object_descripitions",NULL,2,0)); |
---|
| 1548 | |
---|
| 1549 | |
---|
| 1550 | int size=0; |
---|
| 1551 | int i=0; |
---|
| 1552 | for (;i<total_objects;i++) // now save the names of the objects so if ordering |
---|
| 1553 | size+=1+strlen(object_names[i])+1; // changes in future versions we can adjust in load |
---|
| 1554 | sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"describe_names",NULL,size,0)); |
---|
| 1555 | |
---|
| 1556 | |
---|
| 1557 | size=0; |
---|
| 1558 | for (i=0;i<total_objects;i++) |
---|
| 1559 | { |
---|
| 1560 | size+=2; // total number of states |
---|
| 1561 | int j=0; |
---|
| 1562 | for (;j<figures[i]->ts;j++) |
---|
| 1563 | if (figures[i]->seq[j]) |
---|
| 1564 | size+=1+strlen(lstring_value(symbol_name(figures[i]->seq_syms[j])))+1; |
---|
| 1565 | } |
---|
| 1566 | sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"describe_states",NULL,size,0)); |
---|
| 1567 | |
---|
| 1568 | |
---|
| 1569 | |
---|
| 1570 | size=0; |
---|
| 1571 | for (i=0;i<total_objects;i++) |
---|
| 1572 | { |
---|
| 1573 | size+=2; // total number of variables |
---|
| 1574 | int j=0; |
---|
| 1575 | for (;j<figures[i]->tiv;j++) |
---|
| 1576 | if (figures[i]->vars[j]) |
---|
| 1577 | size+=1+strlen(lstring_value(symbol_name(figures[i]->vars[j])))+1; |
---|
| 1578 | } |
---|
| 1579 | sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"describe_lvars",NULL,size,0)); |
---|
| 1580 | |
---|
| 1581 | |
---|
| 1582 | |
---|
[16] | 1583 | // how many objects are we goint to save, use a int32_t to specify how many |
---|
[2] | 1584 | sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"object_list",NULL,4,0)); |
---|
| 1585 | |
---|
[16] | 1586 | int32_t t=0; |
---|
[2] | 1587 | object_node *o=save_list; |
---|
| 1588 | for (;o;o=o->next) |
---|
| 1589 | t++; |
---|
| 1590 | |
---|
| 1591 | // type and state aren't normal records because they will be remapped on loading |
---|
| 1592 | sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"type",NULL,1+2*t,0)); |
---|
| 1593 | sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"state",NULL,1+2*t,0)); |
---|
| 1594 | |
---|
| 1595 | |
---|
| 1596 | // now save all the lvars for each object |
---|
| 1597 | for (size=0,o=save_list;o;o=o->next) |
---|
| 1598 | size+=figures[o->me->otype]->tv*5+2; |
---|
| 1599 | sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"lvars",NULL,size,0)); |
---|
| 1600 | |
---|
| 1601 | |
---|
| 1602 | for (i=0;i<TOTAL_OBJECT_VARS;i++) |
---|
| 1603 | sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,object_descriptions[i].name,NULL,1+ |
---|
| 1604 | RC_type_size(object_descriptions[i].type)*t,0)); |
---|
| 1605 | |
---|
| 1606 | add_light_spec(&sd,Name); |
---|
| 1607 | |
---|
| 1608 | |
---|
| 1609 | sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"object_links",NULL,1+4+total_object_links(save_list)*8,0)); |
---|
| 1610 | sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"light_links",NULL,1+4+total_light_links(save_list)*8,0)); |
---|
| 1611 | |
---|
| 1612 | if (save_all) |
---|
| 1613 | { |
---|
| 1614 | t=0; |
---|
| 1615 | view *v=player_list; |
---|
| 1616 | for (;v;v=v->next) t++; |
---|
| 1617 | sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"player_info",NULL,t*4+4,0)); |
---|
| 1618 | |
---|
| 1619 | int tv=total_view_vars(); |
---|
| 1620 | int i=0; |
---|
| 1621 | for (;i<tv;i++) |
---|
| 1622 | sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,get_view_var_name(i),NULL,1+4*t,0)); |
---|
| 1623 | sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"random_start",NULL,5,0)); |
---|
| 1624 | |
---|
| 1625 | sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"weapon_array",NULL,1+4+total_weapons*4*t,0)); |
---|
| 1626 | |
---|
| 1627 | int name_len=0; |
---|
| 1628 | for (v=player_list;v;v=v->next) |
---|
| 1629 | name_len+=strlen(v->name)+2; |
---|
| 1630 | sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"player_names",NULL,name_len,0)); |
---|
| 1631 | |
---|
[106] | 1632 | sd.add_by_hand(new spec_entry(SPEC_IMAGE,"thumb nail",NULL,4+160*(100+wm->font()->height()*2),0)); |
---|
[2] | 1633 | } |
---|
| 1634 | |
---|
| 1635 | sd.calc_offsets(); |
---|
| 1636 | |
---|
| 1637 | return sd.write(filename); |
---|
| 1638 | } |
---|
| 1639 | |
---|
| 1640 | void scale_put(image *im, image *screen, int x, int y, short new_width, short new_height); |
---|
| 1641 | |
---|
| 1642 | void level::write_thumb_nail(bFILE *fp, image *im) |
---|
| 1643 | { |
---|
[106] | 1644 | image *i=new image(160,100+wm->font()->height()*2); |
---|
[2] | 1645 | i->clear(); |
---|
| 1646 | scale_put(im,i,0,0,160,100); |
---|
| 1647 | if (first_name) |
---|
[106] | 1648 | wm->font()->put_string(i,80-strlen(first_name)*wm->font()->width()/2,100,first_name); |
---|
[2] | 1649 | |
---|
| 1650 | time_t t; |
---|
| 1651 | t=time(NULL); |
---|
| 1652 | char buf[80]; |
---|
| 1653 | |
---|
| 1654 | strftime(buf,80,"%T %A %B %d",localtime(&t)); |
---|
[106] | 1655 | wm->font()->put_string(i,80-strlen(buf)*wm->font()->width()/2,100+wm->font()->height(),buf); |
---|
[2] | 1656 | |
---|
[17] | 1657 | fp->write_uint16(i->width()); |
---|
| 1658 | fp->write_uint16(i->height()); |
---|
[2] | 1659 | int y=0; |
---|
| 1660 | for (;y<i->height();y++) |
---|
| 1661 | fp->write(i->scan_line(y),i->width()); |
---|
| 1662 | |
---|
| 1663 | delete i; |
---|
| 1664 | } |
---|
| 1665 | |
---|
| 1666 | void level::write_player_info(bFILE *fp, object_node *save_list) |
---|
| 1667 | { |
---|
[16] | 1668 | int32_t t=0; |
---|
[2] | 1669 | view *v=player_list; |
---|
| 1670 | for (;v;v=v->next) t++; |
---|
[17] | 1671 | fp->write_uint32(t); |
---|
[2] | 1672 | |
---|
| 1673 | for (v=player_list;v;v=v->next) |
---|
[17] | 1674 | fp->write_uint32(object_to_number_in_list(v->focus,save_list)); |
---|
[2] | 1675 | |
---|
| 1676 | int tv=total_view_vars(); |
---|
| 1677 | int i=0; |
---|
| 1678 | for (;i<tv;i++) |
---|
| 1679 | { |
---|
[18] | 1680 | fp->write_uint8(RC_32); |
---|
[2] | 1681 | for (v=player_list;v;v=v->next) |
---|
[17] | 1682 | fp->write_uint32(v->get_view_var_value(i)); |
---|
[2] | 1683 | } |
---|
| 1684 | |
---|
[18] | 1685 | fp->write_uint8(RC_32); |
---|
[17] | 1686 | fp->write_uint32(rand_on); |
---|
[2] | 1687 | |
---|
[18] | 1688 | fp->write_uint8(RC_32); |
---|
[17] | 1689 | fp->write_uint32(total_weapons); |
---|
[2] | 1690 | for (v=player_list;v;v=v->next) |
---|
| 1691 | for (i=0;i<total_weapons;i++) |
---|
[17] | 1692 | fp->write_uint32(v->weapons[i]); |
---|
[2] | 1693 | |
---|
| 1694 | for (v=player_list;v;v=v->next) |
---|
| 1695 | { |
---|
| 1696 | int len=strlen(v->name)+1; |
---|
[17] | 1697 | fp->write_uint8(len); |
---|
[2] | 1698 | fp->write(v->name,len); |
---|
| 1699 | } |
---|
| 1700 | } |
---|
| 1701 | |
---|
| 1702 | |
---|
| 1703 | int level::load_player_info(bFILE *fp, spec_directory *sd, object_node *save_list) |
---|
| 1704 | { |
---|
| 1705 | int ret; |
---|
| 1706 | spec_entry *se=sd->find("player_info"); |
---|
| 1707 | if (se) |
---|
| 1708 | { |
---|
| 1709 | fp->seek(se->offset,0); |
---|
| 1710 | |
---|
| 1711 | int set_first_view=0; |
---|
| 1712 | if (the_game->first_view==player_list) set_first_view=1; |
---|
| 1713 | int my_player_number=-1; |
---|
| 1714 | |
---|
| 1715 | view *v=player_list; |
---|
| 1716 | for (;v;v=v->next) |
---|
| 1717 | { v->suggest.send_view=0; |
---|
| 1718 | v->suggest.send_weapon_change=0; |
---|
| 1719 | } |
---|
| 1720 | |
---|
| 1721 | for (v=player_list;v;v=v->next) |
---|
| 1722 | if (v->local_player()) |
---|
| 1723 | my_player_number=v->player_number; |
---|
| 1724 | |
---|
| 1725 | while (player_list) // delete all of the views (they will get recreated) |
---|
| 1726 | { |
---|
| 1727 | v=player_list; |
---|
| 1728 | if (v->focus) |
---|
| 1729 | { |
---|
| 1730 | if (v->focus->controller()) |
---|
| 1731 | v->focus->set_controller(NULL); |
---|
| 1732 | delete v->focus; |
---|
| 1733 | } |
---|
| 1734 | |
---|
| 1735 | player_list=player_list->next; |
---|
| 1736 | delete v; |
---|
| 1737 | } |
---|
| 1738 | |
---|
[17] | 1739 | int32_t total_players=fp->read_uint32(); |
---|
[2] | 1740 | view *last=NULL; |
---|
| 1741 | int i=0; |
---|
| 1742 | for (;i<total_players;i++) |
---|
| 1743 | { |
---|
[17] | 1744 | game_object *o=number_to_object_in_list(fp->read_uint32(),save_list); |
---|
[2] | 1745 | v=new view(o,NULL,0); |
---|
| 1746 | if (o) o->set_controller(v); |
---|
| 1747 | if (player_list) |
---|
| 1748 | last->next=v; |
---|
| 1749 | else player_list=v; |
---|
| 1750 | last=v; |
---|
| 1751 | } |
---|
| 1752 | if (set_first_view) |
---|
| 1753 | the_game->first_view=player_list; |
---|
| 1754 | |
---|
| 1755 | for (i=0;i<total_view_vars();i++) |
---|
| 1756 | { |
---|
[39] | 1757 | char const *find_name = get_view_var_name(i); |
---|
[2] | 1758 | se=sd->find(find_name); |
---|
| 1759 | |
---|
| 1760 | if (se) |
---|
| 1761 | { |
---|
| 1762 | fp->seek(se->offset,0); |
---|
[18] | 1763 | if (fp->read_uint8()==RC_32) |
---|
[2] | 1764 | { |
---|
| 1765 | for (v=player_list;v;v=v->next) |
---|
[17] | 1766 | v->set_view_var_value(i,fp->read_uint32()); |
---|
[2] | 1767 | } |
---|
| 1768 | } else |
---|
| 1769 | { |
---|
| 1770 | for (v=player_list;v;v=v->next) |
---|
| 1771 | v->set_view_var_value(i,0); |
---|
| 1772 | } |
---|
| 1773 | } |
---|
| 1774 | |
---|
| 1775 | se=sd->find("random_start"); // start of index into random table |
---|
| 1776 | if (se) |
---|
| 1777 | { |
---|
| 1778 | fp->seek(se->offset,0); |
---|
[18] | 1779 | if (fp->read_uint8()==RC_32) |
---|
[17] | 1780 | rand_on=fp->read_uint32(); |
---|
[2] | 1781 | } else rand_on=0; |
---|
| 1782 | |
---|
| 1783 | se=sd->find("weapon_array"); |
---|
| 1784 | if (se) |
---|
| 1785 | { |
---|
| 1786 | fp->seek(se->offset,0); |
---|
[18] | 1787 | if (fp->read_uint8()==RC_32) |
---|
[2] | 1788 | { |
---|
[17] | 1789 | int32_t m=fp->read_uint32(); // read how many weapons exsisted when last saved |
---|
[2] | 1790 | int i; |
---|
| 1791 | for (v=player_list;v;v=v->next) |
---|
| 1792 | { |
---|
| 1793 | for (i=0;i<m;i++) |
---|
| 1794 | { |
---|
[17] | 1795 | int32_t x=fp->read_uint32(); |
---|
[2] | 1796 | if (i<total_weapons) |
---|
| 1797 | { |
---|
| 1798 | v->weapons[i]=x; |
---|
| 1799 | v->last_weapons[i]=x; |
---|
| 1800 | } |
---|
| 1801 | } |
---|
| 1802 | } |
---|
| 1803 | } |
---|
| 1804 | } else |
---|
| 1805 | { |
---|
| 1806 | for (v=player_list;v;v=v->next) |
---|
| 1807 | { |
---|
[16] | 1808 | memset(v->last_weapons,0xff,total_weapons*sizeof(int32_t)); |
---|
| 1809 | memset(v->weapons,0xff,total_weapons*sizeof(int32_t)); |
---|
[2] | 1810 | } |
---|
| 1811 | } |
---|
| 1812 | |
---|
| 1813 | se=sd->find("player_names"); |
---|
| 1814 | if (se) |
---|
| 1815 | { |
---|
| 1816 | fp->seek(se->offset,0); |
---|
| 1817 | for (v=player_list;v;v=v->next) |
---|
| 1818 | { |
---|
[17] | 1819 | uint8_t len=fp->read_uint8(); |
---|
[2] | 1820 | fp->read(v->name,len); |
---|
| 1821 | } |
---|
| 1822 | } |
---|
| 1823 | |
---|
| 1824 | ret=1; |
---|
| 1825 | recalc_local_view_space(); |
---|
| 1826 | |
---|
| 1827 | } else |
---|
| 1828 | { |
---|
| 1829 | void *fun=make_find_symbol("set_player_defaults"); |
---|
| 1830 | if (DEFINEDP(symbol_function(fun))) |
---|
| 1831 | { |
---|
| 1832 | view *f; |
---|
| 1833 | game_object *o=current_object; |
---|
| 1834 | for (f=player_list;f;f=f->next) |
---|
| 1835 | { |
---|
| 1836 | if (f->focus) |
---|
| 1837 | { |
---|
| 1838 | current_object=f->focus; |
---|
| 1839 | void *m=mark_heap(TMP_SPACE); |
---|
| 1840 | eval_function((lisp_symbol *)fun,NULL); |
---|
| 1841 | restore_heap(m,TMP_SPACE); |
---|
| 1842 | } |
---|
| 1843 | } |
---|
| 1844 | current_object=o; |
---|
| 1845 | } |
---|
| 1846 | ret=0; |
---|
| 1847 | } |
---|
| 1848 | |
---|
| 1849 | view *vw; |
---|
| 1850 | for (vw=player_list;vw;vw=vw->next) |
---|
| 1851 | { |
---|
| 1852 | if (total_weapons && !vw->has_weapon(vw->current_weapon)) |
---|
| 1853 | { |
---|
| 1854 | vw->suggest.send_weapon_change=1; |
---|
| 1855 | vw->suggest.new_weapon=0; |
---|
| 1856 | } |
---|
| 1857 | } |
---|
| 1858 | |
---|
| 1859 | return ret; |
---|
| 1860 | } |
---|
| 1861 | |
---|
| 1862 | |
---|
| 1863 | void level::write_objects(bFILE *fp, object_node *save_list) |
---|
| 1864 | { |
---|
| 1865 | // record information in the file about what the data structures look like |
---|
| 1866 | // right now, so if they change later, they don't get get screwed up |
---|
[17] | 1867 | fp->write_uint16(total_objects); // mark how many objects we know about right now |
---|
[2] | 1868 | |
---|
| 1869 | int i=0; |
---|
| 1870 | for (;i<total_objects;i++) // loop through all the object types we know of |
---|
| 1871 | { |
---|
[17] | 1872 | fp->write_uint8(strlen(object_names[i])+1); // sizeof name |
---|
[2] | 1873 | fp->write(object_names[i],strlen(object_names[i])+1); // write object name |
---|
| 1874 | } |
---|
| 1875 | |
---|
| 1876 | |
---|
| 1877 | // write state numbers and names for each object |
---|
| 1878 | for (i=0;i<total_objects;i++) |
---|
| 1879 | { |
---|
| 1880 | int total=0; |
---|
| 1881 | int j=0; |
---|
| 1882 | for (;j<figures[i]->ts;j++) |
---|
| 1883 | if (figures[i]->seq[j]) total++; |
---|
[17] | 1884 | fp->write_uint16(total); |
---|
[2] | 1885 | |
---|
| 1886 | for (j=0;j<figures[i]->ts;j++) |
---|
| 1887 | if (figures[i]->seq[j]) |
---|
| 1888 | { |
---|
| 1889 | char *state_name=lstring_value(symbol_name(figures[i]->seq_syms[j])); |
---|
[17] | 1890 | fp->write_uint8(strlen(state_name)+1); |
---|
[2] | 1891 | fp->write(state_name,strlen(state_name)+1); |
---|
| 1892 | } |
---|
| 1893 | } |
---|
| 1894 | |
---|
| 1895 | |
---|
| 1896 | // write object lvar names |
---|
| 1897 | for (i=0;i<total_objects;i++) |
---|
| 1898 | { |
---|
[17] | 1899 | fp->write_uint16(figures[i]->tv); |
---|
[2] | 1900 | int j,x; |
---|
| 1901 | |
---|
| 1902 | for (x=0;x<figures[i]->tv;x++) |
---|
| 1903 | { |
---|
| 1904 | for (j=0;j<figures[i]->tiv;j++) |
---|
| 1905 | { |
---|
| 1906 | if (figures[i]->vars[j] && figures[i]->var_index[j]==x) |
---|
| 1907 | { |
---|
| 1908 | char *var_name=lstring_value(symbol_name(figures[i]->vars[j])); |
---|
[17] | 1909 | fp->write_uint8(strlen(var_name)+1); |
---|
[2] | 1910 | fp->write(var_name,strlen(var_name)+1); |
---|
| 1911 | } |
---|
| 1912 | } |
---|
| 1913 | } |
---|
| 1914 | } |
---|
| 1915 | |
---|
[16] | 1916 | int32_t t=0; |
---|
[2] | 1917 | object_node *o=save_list; |
---|
| 1918 | for (;o;o=o->next) t++; |
---|
[17] | 1919 | fp->write_uint32(t); |
---|
[2] | 1920 | |
---|
| 1921 | |
---|
[18] | 1922 | fp->write_uint8(RC_16); // save type info for each record |
---|
[17] | 1923 | for (o=save_list;o;o=o->next) fp->write_uint16(o->me->type()); |
---|
[2] | 1924 | |
---|
[18] | 1925 | fp->write_uint8(RC_16); // save state info for each record |
---|
[17] | 1926 | for (o=save_list;o;o=o->next) fp->write_uint16(o->me->reduced_state()); |
---|
[2] | 1927 | |
---|
| 1928 | for (o=save_list;o;o=o->next) // save lvars |
---|
| 1929 | { |
---|
[17] | 1930 | fp->write_uint16(figures[o->me->otype]->tv); |
---|
[2] | 1931 | for (i=0;i<figures[o->me->otype]->tv;i++) |
---|
| 1932 | { |
---|
[18] | 1933 | fp->write_uint8(RC_32); // for now the only type allowed is int32_t |
---|
[17] | 1934 | fp->write_uint32(o->me->lvars[i]); |
---|
[2] | 1935 | } |
---|
| 1936 | } |
---|
| 1937 | |
---|
| 1938 | for (i=0;i<default_simple.total_vars();i++) |
---|
| 1939 | { |
---|
| 1940 | int t=object_descriptions[i].type; |
---|
[17] | 1941 | fp->write_uint8(t); |
---|
[2] | 1942 | for (o=save_list;o;o=o->next) |
---|
| 1943 | { |
---|
| 1944 | switch (t) |
---|
| 1945 | { |
---|
[18] | 1946 | case RC_8 : |
---|
[17] | 1947 | { fp->write_uint8(o->me->get_var(i)); } break; |
---|
[18] | 1948 | case RC_16 : |
---|
[17] | 1949 | { fp->write_uint16(o->me->get_var(i)); } break; |
---|
[18] | 1950 | case RC_32 : |
---|
[17] | 1951 | { fp->write_uint32(o->me->get_var(i)); } break; |
---|
[2] | 1952 | } |
---|
| 1953 | } |
---|
| 1954 | } |
---|
| 1955 | } |
---|
| 1956 | |
---|
| 1957 | |
---|
[16] | 1958 | int32_t level::total_object_links(object_node *list) |
---|
[2] | 1959 | { |
---|
[16] | 1960 | int32_t tl=0; |
---|
[2] | 1961 | for (object_node *o=list;o;o=o->next) |
---|
| 1962 | tl+=o->me->total_objects(); |
---|
| 1963 | return tl; |
---|
| 1964 | } |
---|
| 1965 | |
---|
[16] | 1966 | int32_t level::total_light_links(object_node *list) |
---|
[2] | 1967 | { |
---|
[16] | 1968 | int32_t tl=0; |
---|
[2] | 1969 | for (object_node *o=list;o;o=o->next) |
---|
| 1970 | tl+=o->me->total_lights(); |
---|
| 1971 | return tl; |
---|
| 1972 | } |
---|
| 1973 | |
---|
| 1974 | void level::write_links(bFILE *fp, object_node *save_list, object_node *exclude_list) |
---|
| 1975 | { |
---|
[18] | 1976 | fp->write_uint8(RC_32); |
---|
[17] | 1977 | fp->write_uint32(total_object_links(save_list)); |
---|
[2] | 1978 | |
---|
| 1979 | int x=1; |
---|
| 1980 | object_node *o=save_list; |
---|
| 1981 | |
---|
| 1982 | for (;o;o=o->next,x++) |
---|
| 1983 | { |
---|
| 1984 | int i=0; |
---|
| 1985 | for (;i<o->me->total_objects();i++) |
---|
| 1986 | { |
---|
[17] | 1987 | fp->write_uint32(x); |
---|
[16] | 1988 | int32_t x=object_to_number_in_list(o->me->get_object(i),save_list); |
---|
[2] | 1989 | if (x) |
---|
[17] | 1990 | fp->write_uint32(x); |
---|
[2] | 1991 | else // save links to excluded items as negative |
---|
[17] | 1992 | fp->write_uint32((int32_t)(-(object_to_number_in_list(o->me,exclude_list)))); |
---|
[2] | 1993 | } |
---|
| 1994 | } |
---|
| 1995 | |
---|
[18] | 1996 | fp->write_uint8(RC_32); |
---|
[17] | 1997 | fp->write_uint32(total_light_links(save_list)); |
---|
[2] | 1998 | |
---|
| 1999 | x=1; |
---|
| 2000 | for (o=save_list;o;o=o->next,x++) |
---|
| 2001 | { |
---|
| 2002 | int i=0; |
---|
| 2003 | for (;i<o->me->total_lights();i++) |
---|
| 2004 | { |
---|
[17] | 2005 | fp->write_uint32(x); |
---|
| 2006 | fp->write_uint32(light_to_number(o->me->get_light(i))); |
---|
[2] | 2007 | } |
---|
| 2008 | } |
---|
| 2009 | |
---|
| 2010 | } |
---|
| 2011 | |
---|
| 2012 | |
---|
| 2013 | void level::load_links(bFILE *fp, spec_directory *sd, |
---|
| 2014 | object_node *save_list, object_node *exclude_list) |
---|
| 2015 | { |
---|
| 2016 | spec_entry *se=sd->find("object_links"); |
---|
| 2017 | if (se) |
---|
| 2018 | { |
---|
| 2019 | fp->seek(se->offset,0); |
---|
[18] | 2020 | if (fp->read_uint8()==RC_32) |
---|
[2] | 2021 | { |
---|
[17] | 2022 | int32_t t=fp->read_uint32(); |
---|
[2] | 2023 | while (t) |
---|
| 2024 | { |
---|
[17] | 2025 | int32_t x1=fp->read_uint32(); |
---|
[2] | 2026 | CONDITION(x1>=0,"expected x1 for object link to be > 0\n"); |
---|
[17] | 2027 | int32_t x2=fp->read_uint32(); |
---|
[2] | 2028 | game_object *p,*q=number_to_object_in_list(x1,save_list); |
---|
| 2029 | if (x2>0) |
---|
| 2030 | p=number_to_object_in_list(x2,save_list); |
---|
| 2031 | else p=number_to_object_in_list(-x2,exclude_list); |
---|
| 2032 | if (q) |
---|
| 2033 | q->add_object(p); |
---|
| 2034 | else dprintf("bad object link\n"); |
---|
| 2035 | |
---|
| 2036 | t--; |
---|
| 2037 | } |
---|
| 2038 | } |
---|
| 2039 | } |
---|
| 2040 | |
---|
| 2041 | se=sd->find("light_links"); |
---|
| 2042 | if (se) |
---|
| 2043 | { |
---|
| 2044 | fp->seek(se->offset,0); |
---|
[18] | 2045 | if (fp->read_uint8()==RC_32) |
---|
[2] | 2046 | { |
---|
[17] | 2047 | int32_t t=fp->read_uint32(); |
---|
[2] | 2048 | while (t) |
---|
| 2049 | { |
---|
[17] | 2050 | int32_t x1=fp->read_uint32(); |
---|
| 2051 | int32_t x2=fp->read_uint32(); |
---|
[2] | 2052 | game_object *p=number_to_object_in_list(x1,save_list); |
---|
| 2053 | if (p) |
---|
| 2054 | p->add_light(number_to_light(x2)); |
---|
| 2055 | else dprintf("bad object/light link\n"); |
---|
| 2056 | t--; |
---|
| 2057 | } |
---|
| 2058 | } |
---|
| 2059 | } |
---|
| 2060 | |
---|
| 2061 | } |
---|
| 2062 | |
---|
| 2063 | |
---|
| 2064 | void level::write_options(bFILE *fp) |
---|
| 2065 | { |
---|
| 2066 | // save background scroll rate |
---|
[18] | 2067 | fp->write_uint8(RC_32); |
---|
[17] | 2068 | fp->write_uint32(bg_xmul); |
---|
| 2069 | fp->write_uint32(bg_xdiv); |
---|
| 2070 | fp->write_uint32(bg_ymul); |
---|
| 2071 | fp->write_uint32(bg_ydiv); |
---|
[2] | 2072 | |
---|
[18] | 2073 | fp->write_uint8(RC_32); |
---|
[2] | 2074 | int ta=0; |
---|
| 2075 | area_controller *a=area_list; |
---|
| 2076 | for (;a;a=a->next) ta++; |
---|
[17] | 2077 | fp->write_uint32(ta); |
---|
[2] | 2078 | for (a=area_list;a;a=a->next) |
---|
| 2079 | { |
---|
[17] | 2080 | fp->write_uint32(a->x); |
---|
| 2081 | fp->write_uint32(a->y); |
---|
| 2082 | fp->write_uint32(a->w); |
---|
| 2083 | fp->write_uint32(a->h); |
---|
| 2084 | fp->write_uint32(a->active); |
---|
[2] | 2085 | |
---|
[17] | 2086 | fp->write_uint32(a->ambient); |
---|
| 2087 | fp->write_uint32(a->view_xoff); |
---|
| 2088 | fp->write_uint32(a->view_yoff); |
---|
| 2089 | fp->write_uint32(a->ambient_speed); |
---|
| 2090 | fp->write_uint32(a->view_xoff_speed); |
---|
| 2091 | fp->write_uint32(a->view_yoff_speed); |
---|
[2] | 2092 | } |
---|
[18] | 2093 | fp->write_uint8(RC_32); |
---|
[17] | 2094 | fp->write_uint32(tick_counter()); |
---|
[2] | 2095 | } |
---|
| 2096 | |
---|
| 2097 | void level::load_options(spec_directory *sd, bFILE *fp) |
---|
| 2098 | { |
---|
| 2099 | spec_entry *se=sd->find("bg_scroll_rate"); |
---|
| 2100 | if (se) |
---|
| 2101 | { |
---|
| 2102 | fp->seek(se->offset,0); |
---|
[18] | 2103 | if (fp->read_uint8()!=RC_32) |
---|
[2] | 2104 | { bg_xmul=bg_ymul=1; bg_xdiv=bg_ydiv=8; } |
---|
| 2105 | else |
---|
| 2106 | { |
---|
[17] | 2107 | bg_xmul=fp->read_uint32(); |
---|
| 2108 | bg_xdiv=fp->read_uint32(); |
---|
| 2109 | bg_ymul=fp->read_uint32(); |
---|
| 2110 | bg_ydiv=fp->read_uint32(); |
---|
[2] | 2111 | } |
---|
| 2112 | } else { bg_xmul=bg_ymul=1; bg_xdiv=bg_ydiv=8; } |
---|
| 2113 | |
---|
| 2114 | se=sd->find("area_list.v1"); |
---|
| 2115 | if (se) |
---|
| 2116 | { |
---|
| 2117 | fp->seek(se->offset,0); |
---|
[18] | 2118 | if (fp->read_uint8()==RC_32) |
---|
[2] | 2119 | { |
---|
| 2120 | area_controller *l=NULL,*p; |
---|
[17] | 2121 | int32_t ta=fp->read_uint32(); |
---|
[2] | 2122 | int i=0; |
---|
| 2123 | for (;i<ta;i++) |
---|
| 2124 | { |
---|
[16] | 2125 | int32_t x,y,w,h; |
---|
[17] | 2126 | x=fp->read_uint32(); |
---|
| 2127 | y=fp->read_uint32(); |
---|
| 2128 | w=fp->read_uint32(); |
---|
| 2129 | h=fp->read_uint32(); |
---|
[2] | 2130 | p=new area_controller(x,y,w,h,NULL); |
---|
| 2131 | if (l) l->next=p; |
---|
| 2132 | else area_list=p; |
---|
| 2133 | l=p; |
---|
[17] | 2134 | p->active=fp->read_uint32(); |
---|
| 2135 | p->ambient=fp->read_uint32(); |
---|
| 2136 | p->view_xoff=fp->read_uint32(); |
---|
| 2137 | p->view_yoff=fp->read_uint32(); |
---|
| 2138 | p->ambient_speed=fp->read_uint32(); |
---|
| 2139 | p->view_xoff_speed=fp->read_uint32(); |
---|
| 2140 | p->view_yoff_speed=fp->read_uint32(); |
---|
[2] | 2141 | } |
---|
| 2142 | } |
---|
| 2143 | } |
---|
| 2144 | |
---|
| 2145 | se=sd->find("tick_counter"); |
---|
| 2146 | if (se) |
---|
| 2147 | { |
---|
| 2148 | fp->seek(se->offset,0); |
---|
[18] | 2149 | if (fp->read_uint8()==RC_32) |
---|
[17] | 2150 | set_tick_counter(fp->read_uint32()); |
---|
[2] | 2151 | else set_tick_counter(0); |
---|
| 2152 | } else set_tick_counter(0); |
---|
| 2153 | } |
---|
| 2154 | |
---|
| 2155 | |
---|
| 2156 | void level::write_cache_prof_info() |
---|
| 2157 | { |
---|
| 2158 | if (cash.prof_is_on()) |
---|
| 2159 | { |
---|
| 2160 | char pf_name[100]; |
---|
| 2161 | if (first_name) |
---|
| 2162 | get_prof_assoc_filename(first_name,pf_name); |
---|
| 2163 | else |
---|
| 2164 | get_prof_assoc_filename(Name,pf_name); |
---|
| 2165 | |
---|
| 2166 | |
---|
| 2167 | spec_directory sd; |
---|
| 2168 | sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"cache profile info",NULL,cash.prof_size(),0)); |
---|
| 2169 | sd.calc_offsets(); |
---|
| 2170 | jFILE *fp2=sd.write(pf_name); |
---|
| 2171 | if (!fp2) |
---|
| 2172 | the_game->show_help("Unable to open cache profile output file"); |
---|
| 2173 | else |
---|
| 2174 | { |
---|
| 2175 | cash.prof_write(fp2); |
---|
| 2176 | delete fp2; |
---|
| 2177 | } |
---|
| 2178 | sd.delete_entries(); |
---|
| 2179 | } |
---|
| 2180 | |
---|
| 2181 | } |
---|
| 2182 | |
---|
| 2183 | void level::load_cache_info(spec_directory *sd, bFILE *fp) |
---|
| 2184 | { |
---|
| 2185 | if (!DEFINEDP(symbol_value(l_empty_cache)) || !symbol_value(l_empty_cache)) |
---|
| 2186 | { |
---|
| 2187 | char pf_name[100]; |
---|
| 2188 | if (first_name) |
---|
| 2189 | get_prof_assoc_filename(first_name,pf_name); // get cache info from orignal filename if this is a savegame |
---|
| 2190 | else |
---|
| 2191 | get_prof_assoc_filename(Name,pf_name); |
---|
| 2192 | |
---|
| 2193 | |
---|
| 2194 | cash.load_cache_prof_info(pf_name,this); |
---|
| 2195 | } |
---|
| 2196 | } |
---|
| 2197 | |
---|
| 2198 | |
---|
[39] | 2199 | int level::save(char const *filename, int save_all) |
---|
[2] | 2200 | { |
---|
| 2201 | char name[255], bkname[255]; |
---|
| 2202 | |
---|
| 2203 | sprintf( name, "%s%s", get_save_filename_prefix(), filename ); |
---|
| 2204 | sprintf( bkname, "%slevsave.bak", get_save_filename_prefix() ); |
---|
| 2205 | if( !save_all && DEFINEDP( symbol_value( l_keep_backup ) ) && |
---|
| 2206 | symbol_value( l_keep_backup ) ) // make a backup |
---|
| 2207 | { |
---|
| 2208 | bFILE *fp = open_file( name, "rb" ); // does file already exist? |
---|
| 2209 | if( !fp->open_failure() ) |
---|
| 2210 | { |
---|
| 2211 | unlink( bkname ); |
---|
| 2212 | bFILE *bk = open_file( bkname, "wb" ); |
---|
| 2213 | if( bk->open_failure() ) |
---|
| 2214 | dprintf("unable to open backup file %s\n", bkname ); |
---|
| 2215 | else |
---|
| 2216 | { |
---|
[16] | 2217 | int32_t size = fp->file_size(); |
---|
[17] | 2218 | uint8_t *buf = (uint8_t *)jmalloc(0x1000,"copy buf"); |
---|
[2] | 2219 | int tr = 1; |
---|
| 2220 | while( size && tr ) |
---|
| 2221 | { |
---|
| 2222 | int tr = fp->read(buf,0x1000); |
---|
| 2223 | if( tr ) |
---|
| 2224 | tr = bk->write(buf,tr); |
---|
| 2225 | size -= tr; |
---|
| 2226 | } |
---|
| 2227 | jfree(buf); |
---|
| 2228 | } |
---|
| 2229 | delete bk; |
---|
| 2230 | #if (defined(__MACH__) || !defined(__APPLE__)) |
---|
| 2231 | chmod( bkname, S_IRWXU | S_IRWXG | S_IRWXO ); |
---|
| 2232 | #endif |
---|
| 2233 | } |
---|
| 2234 | delete fp; |
---|
| 2235 | } |
---|
| 2236 | |
---|
| 2237 | // if we are not doing a savegame then change the first_name to this name |
---|
| 2238 | if( !save_all ) |
---|
| 2239 | { |
---|
| 2240 | if( first_name ) |
---|
| 2241 | jfree(first_name); |
---|
| 2242 | first_name = (char *)jmalloc( strlen( name ) + 1, "level first name" ); |
---|
| 2243 | strcpy( first_name, name ); |
---|
| 2244 | } |
---|
| 2245 | |
---|
| 2246 | object_node *players, *objs; |
---|
| 2247 | if( save_all ) |
---|
| 2248 | players = NULL; |
---|
| 2249 | else |
---|
| 2250 | players = make_player_onodes(); |
---|
| 2251 | |
---|
| 2252 | objs = make_not_list(players); // negate the above list |
---|
| 2253 | |
---|
| 2254 | bFILE *fp = create_dir( name, save_all, objs, players); |
---|
| 2255 | if( fp != NULL ) |
---|
| 2256 | { |
---|
| 2257 | if( !fp->open_failure() ) |
---|
| 2258 | { |
---|
| 2259 | if( first_name ) |
---|
| 2260 | { |
---|
[17] | 2261 | fp->write_uint8( strlen( first_name ) + 1 ); |
---|
[2] | 2262 | fp->write( first_name, strlen( first_name ) + 1 ); |
---|
| 2263 | } |
---|
| 2264 | else |
---|
| 2265 | { |
---|
[17] | 2266 | fp->write_uint8( 1 ); |
---|
| 2267 | fp->write_uint8( 0 ); |
---|
[2] | 2268 | } |
---|
| 2269 | |
---|
[17] | 2270 | fp->write_uint32( fg_width ); |
---|
| 2271 | fp->write_uint32( fg_height ); |
---|
[2] | 2272 | |
---|
| 2273 | int t = fg_width * fg_height; |
---|
[17] | 2274 | uint16_t *rm = map_fg; |
---|
[2] | 2275 | for (;t;t--,rm++) |
---|
| 2276 | { |
---|
[17] | 2277 | uint16_t x = *rm; |
---|
[2] | 2278 | x = lstl(x); // convert to intel endianess |
---|
| 2279 | *rm = x; |
---|
| 2280 | } |
---|
| 2281 | |
---|
| 2282 | fp->write( (char *)map_fg, 2 * fg_width * fg_height ); |
---|
| 2283 | t = fg_width * fg_height; |
---|
| 2284 | rm = map_fg; |
---|
| 2285 | for (;t;t--,rm++) |
---|
| 2286 | { |
---|
[17] | 2287 | uint16_t x = *rm; |
---|
[2] | 2288 | x = lstl( x ); // convert to intel endianess |
---|
| 2289 | *rm = x; |
---|
| 2290 | } |
---|
| 2291 | |
---|
[17] | 2292 | fp->write_uint32( bg_width ); |
---|
| 2293 | fp->write_uint32( bg_height ); |
---|
[2] | 2294 | t = bg_width * bg_height; |
---|
| 2295 | rm = map_bg; |
---|
| 2296 | |
---|
| 2297 | for (;t;t--,rm++) |
---|
| 2298 | { |
---|
[17] | 2299 | uint16_t x=*rm; |
---|
[2] | 2300 | x = lstl( x ); // convert to intel endianess |
---|
| 2301 | *rm = x; |
---|
| 2302 | } |
---|
| 2303 | |
---|
| 2304 | fp->write( (char *)map_bg, 2 * bg_width * bg_height ); |
---|
| 2305 | rm = map_bg; |
---|
| 2306 | t = bg_width*bg_height; |
---|
| 2307 | |
---|
| 2308 | for (;t;t--,rm++) |
---|
| 2309 | { |
---|
[17] | 2310 | uint16_t x = *rm; |
---|
[2] | 2311 | x = lstl( x ); // convert to intel endianess |
---|
| 2312 | *rm = x; |
---|
| 2313 | } |
---|
| 2314 | |
---|
| 2315 | write_options( fp ); |
---|
| 2316 | write_objects( fp, objs ); |
---|
| 2317 | write_lights( fp ); |
---|
| 2318 | write_links( fp, objs, players ); |
---|
| 2319 | if( save_all ) |
---|
| 2320 | { |
---|
| 2321 | write_player_info( fp, objs ); |
---|
| 2322 | write_thumb_nail( fp,screen ); |
---|
| 2323 | } |
---|
| 2324 | |
---|
| 2325 | delete fp; |
---|
| 2326 | #if (defined(__MACH__) || !defined(__APPLE__)) |
---|
| 2327 | chmod( name, S_IRWXU | S_IRWXG | S_IRWXO ); |
---|
| 2328 | #endif |
---|
| 2329 | write_cache_prof_info(); |
---|
| 2330 | } |
---|
| 2331 | else |
---|
| 2332 | { |
---|
| 2333 | the_game->show_help( "Unable to open file for saving\n" ); |
---|
| 2334 | delete fp; |
---|
| 2335 | return 0; |
---|
| 2336 | } |
---|
| 2337 | } |
---|
| 2338 | else |
---|
| 2339 | { |
---|
| 2340 | the_game->show_help( "Unable to open file for saving.\n" ); |
---|
| 2341 | printf( "\nFailed to save game.\n" ); |
---|
| 2342 | printf( "I was trying to save to: '%s'\n\tPath: '%s'\n\tFile: '%s'\n", name, get_save_filename_prefix(), filename ); |
---|
| 2343 | printf( "\nPlease send an email to:\n\ttrandor@labyrinth.net.au\nwith these details.\nThanks.\n" ); |
---|
| 2344 | return 0; |
---|
| 2345 | } |
---|
| 2346 | |
---|
| 2347 | delete_object_list(players); |
---|
| 2348 | delete_object_list(objs); |
---|
| 2349 | |
---|
| 2350 | return 1; |
---|
| 2351 | } |
---|
| 2352 | |
---|
[39] | 2353 | level::level(int width, int height, char const *name) |
---|
[2] | 2354 | { |
---|
| 2355 | the_game->need_refresh(); |
---|
| 2356 | area_list=NULL; |
---|
| 2357 | set_tick_counter(0); |
---|
| 2358 | |
---|
| 2359 | attack_list=NULL; |
---|
| 2360 | attack_list_size=attack_total=0; |
---|
| 2361 | |
---|
| 2362 | target_list=NULL; |
---|
| 2363 | target_list_size=target_total=0; |
---|
| 2364 | |
---|
| 2365 | block_list=NULL; |
---|
| 2366 | block_list_size=block_total=0; |
---|
| 2367 | |
---|
| 2368 | all_block_list=NULL; |
---|
| 2369 | all_block_list_size=all_block_total=0; |
---|
| 2370 | |
---|
| 2371 | Name=NULL; |
---|
| 2372 | first_name=NULL; |
---|
| 2373 | |
---|
| 2374 | set_name(name); |
---|
| 2375 | first=first_active=NULL; |
---|
| 2376 | |
---|
| 2377 | fg_width=width; |
---|
| 2378 | fg_height=height; |
---|
| 2379 | calc_bgsize(fg_width,fg_height,bg_width,bg_height); |
---|
| 2380 | |
---|
[16] | 2381 | map_bg=(uint16_t *)jmalloc(sizeof(int16_t)*bg_width*bg_height,"map bg"); |
---|
| 2382 | map_fg=(uint16_t *)jmalloc(sizeof(int16_t)*fg_width*fg_height,"map fg"); |
---|
[2] | 2383 | |
---|
| 2384 | |
---|
| 2385 | |
---|
[16] | 2386 | memset(map_bg,0,sizeof(int16_t)*bg_width*bg_height); |
---|
| 2387 | memset(map_fg,0,sizeof(int16_t)*fg_width*fg_height); |
---|
[2] | 2388 | |
---|
| 2389 | int i; |
---|
| 2390 | for (i=0;i<fg_width;i++) |
---|
| 2391 | { |
---|
| 2392 | map_fg[i]=1; |
---|
| 2393 | map_fg[fg_width*(fg_height-1)+i]=1; |
---|
| 2394 | } |
---|
| 2395 | for (i=0;i<fg_height;i++) |
---|
| 2396 | { |
---|
| 2397 | map_fg[fg_width*i]=1; |
---|
| 2398 | map_fg[fg_width*i+fg_width-1]=1; |
---|
| 2399 | } |
---|
| 2400 | |
---|
| 2401 | total_objs=0; |
---|
| 2402 | insert_players(); |
---|
| 2403 | } |
---|
| 2404 | |
---|
| 2405 | |
---|
| 2406 | void level::add_object(game_object *new_guy) |
---|
| 2407 | { |
---|
| 2408 | total_objs++; |
---|
| 2409 | new_guy->next=NULL; |
---|
| 2410 | if (figures[new_guy->otype]->get_cflag(CFLAG_ADD_FRONT)) |
---|
| 2411 | { |
---|
| 2412 | if (!first) |
---|
| 2413 | first=new_guy; |
---|
| 2414 | else |
---|
| 2415 | last->next=new_guy; |
---|
| 2416 | last=new_guy; |
---|
| 2417 | } else |
---|
| 2418 | { |
---|
| 2419 | if (!first) |
---|
| 2420 | last=first=new_guy; |
---|
| 2421 | else |
---|
| 2422 | { |
---|
| 2423 | new_guy->next=first; |
---|
| 2424 | first=new_guy; |
---|
| 2425 | } |
---|
| 2426 | } |
---|
| 2427 | } |
---|
| 2428 | |
---|
| 2429 | void level::add_object_after(game_object *new_guy,game_object *who) |
---|
| 2430 | { |
---|
| 2431 | if (!who) add_object(new_guy); |
---|
| 2432 | else |
---|
| 2433 | { |
---|
| 2434 | total_objs++; |
---|
| 2435 | if (who==last) last=new_guy; |
---|
| 2436 | new_guy->next=who->next; |
---|
| 2437 | who->next=new_guy; |
---|
| 2438 | } |
---|
| 2439 | } |
---|
| 2440 | |
---|
| 2441 | void level::delete_object(game_object *who) |
---|
| 2442 | { |
---|
| 2443 | remove_object(who); |
---|
| 2444 | delete who; |
---|
| 2445 | } |
---|
| 2446 | |
---|
| 2447 | void level::remove_block(game_object *who) |
---|
| 2448 | { |
---|
| 2449 | int i=0,j; |
---|
| 2450 | game_object **o=block_list; |
---|
| 2451 | for (;i<block_total;i++) |
---|
| 2452 | { |
---|
| 2453 | if (*o==who) // is this object in the block list? |
---|
| 2454 | { |
---|
| 2455 | block_total--; // squish the block list in |
---|
| 2456 | o++; |
---|
| 2457 | for (j=i;j<block_total;j++) |
---|
| 2458 | block_list[j]=block_list[j+1]; |
---|
| 2459 | } else o++; |
---|
| 2460 | } |
---|
| 2461 | } |
---|
| 2462 | |
---|
| 2463 | |
---|
| 2464 | // searches through the all_block list for who and if it finds it deletes it |
---|
| 2465 | void level::remove_all_block(game_object *who) |
---|
| 2466 | { |
---|
| 2467 | int i=0,j; |
---|
| 2468 | game_object **o=all_block_list; |
---|
| 2469 | for (;i<all_block_total;i++) |
---|
| 2470 | { |
---|
| 2471 | if (*o==who) // is this object in the block list? |
---|
| 2472 | { |
---|
| 2473 | all_block_total--; // squish the block list in |
---|
| 2474 | o++; |
---|
| 2475 | for (j=i;j<all_block_total;j++) |
---|
| 2476 | all_block_list[j]=all_block_list[j+1]; |
---|
| 2477 | } else o++; |
---|
| 2478 | } |
---|
| 2479 | } |
---|
| 2480 | |
---|
| 2481 | void level::remove_object(game_object *who) |
---|
| 2482 | { |
---|
| 2483 | if (dev_cont) |
---|
| 2484 | dev_cont->notify_deleted_object(who); |
---|
| 2485 | |
---|
| 2486 | if (who==first) |
---|
| 2487 | { |
---|
| 2488 | if (who==last) last=NULL; |
---|
| 2489 | first=first->next; |
---|
| 2490 | } |
---|
| 2491 | else |
---|
| 2492 | { |
---|
| 2493 | game_object *o=first; |
---|
| 2494 | for (;o && o->next!=who;o=o->next); |
---|
| 2495 | if (o) |
---|
| 2496 | { |
---|
| 2497 | o->next=who->next; |
---|
| 2498 | if (!o->next) last=o; |
---|
| 2499 | } |
---|
| 2500 | else return ; // if object is not in level, don't try to do anything else |
---|
| 2501 | } |
---|
| 2502 | total_objs--; |
---|
| 2503 | |
---|
| 2504 | |
---|
| 2505 | if (first_active==who) |
---|
| 2506 | first_active=who->next_active; |
---|
| 2507 | else |
---|
| 2508 | { |
---|
| 2509 | game_object *o=first_active; |
---|
| 2510 | for (;o && o->next_active!=who;o=o->next_active); |
---|
| 2511 | if (o) |
---|
| 2512 | o->next_active=who->next_active; |
---|
| 2513 | } |
---|
| 2514 | |
---|
| 2515 | if (who->flags()&KNOWN_FLAG) |
---|
| 2516 | { |
---|
| 2517 | game_object *o=first; |
---|
| 2518 | for (;o;o=o->next) |
---|
| 2519 | { |
---|
| 2520 | int t=o->total_objects(); |
---|
| 2521 | int i=0; |
---|
| 2522 | for (;i<t;i++) |
---|
| 2523 | if (o->get_object(i)==who) |
---|
| 2524 | { |
---|
| 2525 | o->remove_object(who); |
---|
| 2526 | t=o->total_objects(); |
---|
| 2527 | } |
---|
| 2528 | } |
---|
| 2529 | } |
---|
| 2530 | |
---|
| 2531 | if (who->otype<0xffff) |
---|
| 2532 | { |
---|
| 2533 | if (who->can_block()) // remove object from block list and all_block if nessasary |
---|
| 2534 | { |
---|
| 2535 | remove_block(who); |
---|
| 2536 | remove_all_block(who); |
---|
| 2537 | } else if (who->hurtable()) |
---|
| 2538 | remove_all_block(who); |
---|
| 2539 | } |
---|
| 2540 | |
---|
| 2541 | |
---|
| 2542 | int t=who->total_objects(); |
---|
| 2543 | while (t) { who->remove_object(who->get_object(0)); t--; } |
---|
| 2544 | |
---|
| 2545 | t=who->total_lights(); |
---|
| 2546 | while (t) { who->remove_light(who->get_light(0)); t--; } |
---|
| 2547 | } |
---|
| 2548 | |
---|
| 2549 | void level::to_front(game_object *o) // move to end of list, so we are drawn last, therefore top |
---|
| 2550 | { |
---|
| 2551 | if (o==last) return ; |
---|
| 2552 | first_active=NULL; // make sure nothing goes screwy with the active list |
---|
| 2553 | |
---|
| 2554 | if (o==first) |
---|
| 2555 | first=first->next; |
---|
| 2556 | else |
---|
| 2557 | { |
---|
| 2558 | game_object *w=first; |
---|
| 2559 | for (;w && w->next!=o;w=w->next); |
---|
| 2560 | if (!w) return ; |
---|
| 2561 | w->next=o->next; |
---|
| 2562 | } |
---|
| 2563 | |
---|
| 2564 | last->next=o; |
---|
| 2565 | o->next=NULL; |
---|
| 2566 | last=o; |
---|
| 2567 | } |
---|
| 2568 | |
---|
| 2569 | void level::to_back(game_object *o) // to make the character drawn in back, put at front of list |
---|
| 2570 | { |
---|
| 2571 | if (o==first) return; |
---|
| 2572 | first_active=NULL; // make sure nothing goes screwy with the active list |
---|
| 2573 | |
---|
| 2574 | game_object *w=first; |
---|
| 2575 | for (;w && w->next!=o;w=w->next); |
---|
| 2576 | if (!w) return; |
---|
| 2577 | if (last==o) |
---|
| 2578 | last=w; |
---|
| 2579 | w->next=o->next; |
---|
| 2580 | o->next=first; |
---|
| 2581 | first=o; |
---|
| 2582 | } |
---|
| 2583 | |
---|
| 2584 | |
---|
| 2585 | game_object *level::find_self(game_object *me) |
---|
| 2586 | { |
---|
| 2587 | return me; |
---|
| 2588 | } |
---|
| 2589 | |
---|
[16] | 2590 | game_object *level::find_object(int32_t x, int32_t y) |
---|
[2] | 2591 | { |
---|
[16] | 2592 | int32_t x1,y1,x2,y2; |
---|
[2] | 2593 | game_object *o=first; |
---|
| 2594 | for (;o;o=o->next) |
---|
| 2595 | { |
---|
| 2596 | o->picture_space(x1,y1,x2,y2); |
---|
| 2597 | if (x<x2 && x>=x1 && y<y2 && y>=y1) |
---|
| 2598 | return o; |
---|
| 2599 | } |
---|
| 2600 | return NULL; |
---|
| 2601 | } |
---|
| 2602 | |
---|
[16] | 2603 | int32_t last_tile_hit_x,last_tile_hit_y; |
---|
[2] | 2604 | |
---|
| 2605 | #define remapx(x) (x==0 ? -1 : x==tl-1 ? tl+1 : x) |
---|
| 2606 | #define remapy(y) (y==0 ? -1 : y==th-1 ? th+1 : y) |
---|
| 2607 | |
---|
[16] | 2608 | void level::foreground_intersect(int32_t x1, int32_t y1, int32_t &x2, int32_t &y2) |
---|
[2] | 2609 | { |
---|
| 2610 | /* if (x1==x2) |
---|
| 2611 | { vforeground_intersect(x1,y1,y2); |
---|
| 2612 | return ; |
---|
| 2613 | } */ |
---|
| 2614 | |
---|
[16] | 2615 | int32_t tl=the_game->ftile_width(),th=the_game->ftile_height(), |
---|
[2] | 2616 | j, |
---|
| 2617 | xp1,yp1,xp2,yp2, // starting and ending points of block line segment |
---|
| 2618 | swap; // temp var |
---|
[16] | 2619 | int32_t blockx1,blocky1,blockx2,blocky2,block,bx,by; |
---|
[2] | 2620 | point_list *block_list; |
---|
| 2621 | unsigned char *bdat; |
---|
| 2622 | |
---|
| 2623 | blockx1=x1; |
---|
| 2624 | blocky1=y1; |
---|
| 2625 | blockx2=x2; |
---|
| 2626 | blocky2=y2; |
---|
| 2627 | if (blockx1>blockx2) { swap=blockx1; blockx1=blockx2; blockx2=swap; } |
---|
| 2628 | if (blocky1>blocky2) { swap=blocky1; blocky1=blocky2; blocky2=swap; } |
---|
| 2629 | blockx1=(blockx1-2)/tl-1; |
---|
| 2630 | blockx2=(blockx2+tl+2)/tl+1; |
---|
| 2631 | blocky1=(blocky1-2)/th-1; |
---|
| 2632 | blocky2=(blocky2+th+2)/th+1; |
---|
| 2633 | |
---|
| 2634 | |
---|
| 2635 | if (blockx2>=foreground_width()) { x2=tl*foreground_width()-1; } |
---|
| 2636 | if (blocky2>=foreground_height()) { y2=th*foreground_height()-1; } |
---|
| 2637 | blockx1=max(blockx1,0); |
---|
| 2638 | blocky1=max(blocky1,0); |
---|
| 2639 | |
---|
| 2640 | if ((blockx1>blockx2) || (blocky1>blocky2)) return ; |
---|
| 2641 | |
---|
| 2642 | // now check all the map positions this line could intersect |
---|
| 2643 | for (bx=blockx1;bx<=blockx2;bx++) |
---|
| 2644 | { |
---|
| 2645 | for (by=blocky1;by<=blocky2;by++) |
---|
| 2646 | { |
---|
| 2647 | block=the_game->get_map_fg(bx,by); |
---|
| 2648 | if (block>BLACK) // don't check BLACK, should be no points in it |
---|
| 2649 | { |
---|
| 2650 | // now check the all the line segments in the block |
---|
| 2651 | foretile *f=the_game->get_fg(block); |
---|
| 2652 | block_list=f->points; |
---|
| 2653 | unsigned char total=block_list->tot; |
---|
| 2654 | bdat=block_list->data; |
---|
| 2655 | unsigned char *ins=f->points->inside; |
---|
[16] | 2656 | int32_t xo=bx*tl,yo=by*th; |
---|
[2] | 2657 | for (j=0;j<total-1;j++,ins++) |
---|
| 2658 | { |
---|
| 2659 | // find the starting and ending points for this segment |
---|
| 2660 | xp1=xo+remapx(*bdat); |
---|
| 2661 | bdat++; |
---|
| 2662 | |
---|
| 2663 | yp1=yo+remapy(*bdat); |
---|
| 2664 | bdat++; |
---|
| 2665 | |
---|
| 2666 | xp2=xo+remapx(*bdat); |
---|
| 2667 | yp2=yo+remapy(bdat[1]); |
---|
| 2668 | |
---|
| 2669 | |
---|
[16] | 2670 | int32_t ox2=x2,oy2=y2; |
---|
[2] | 2671 | if (*ins) |
---|
| 2672 | setback_intersect(x1,y1,x2,y2,xp1,yp1,xp2,yp2,1); |
---|
| 2673 | else |
---|
| 2674 | setback_intersect(x1,y1,x2,y2,xp1,yp1,xp2,yp2,-1); |
---|
| 2675 | if (ox2!=x2 || oy2!=y2) |
---|
| 2676 | { |
---|
| 2677 | last_tile_hit_x=bx; |
---|
| 2678 | last_tile_hit_y=by; |
---|
| 2679 | } |
---|
| 2680 | |
---|
| 2681 | } |
---|
| 2682 | } |
---|
| 2683 | } |
---|
| 2684 | } |
---|
| 2685 | } |
---|
| 2686 | |
---|
| 2687 | |
---|
[16] | 2688 | void level::vforeground_intersect(int32_t x1, int32_t y1, int32_t &y2) |
---|
[2] | 2689 | { |
---|
[16] | 2690 | int32_t tl=f_wid,th=f_hi, |
---|
[2] | 2691 | j, |
---|
| 2692 | xp1,yp1,xp2,yp2; // starting and ending points of block line segment temp var |
---|
[16] | 2693 | int32_t blocky1,blocky2,block,bx,by,checkx; |
---|
[2] | 2694 | point_list *block_list; |
---|
| 2695 | unsigned char *bdat; |
---|
| 2696 | |
---|
| 2697 | int y_addback; |
---|
| 2698 | if (y1>y2) |
---|
| 2699 | { |
---|
| 2700 | blocky1=y2/th; |
---|
| 2701 | blocky2=y1/th; |
---|
| 2702 | y_addback=blocky2*f_hi; |
---|
| 2703 | } else |
---|
| 2704 | { |
---|
| 2705 | blocky1=y1/th; |
---|
| 2706 | blocky2=y2/th; |
---|
| 2707 | y_addback=blocky1*f_hi; |
---|
| 2708 | } |
---|
| 2709 | |
---|
| 2710 | y1-=y_addback; |
---|
| 2711 | y2-=y_addback; |
---|
| 2712 | |
---|
| 2713 | bx=x1/f_wid; |
---|
| 2714 | checkx=x1-bx*f_wid; |
---|
| 2715 | |
---|
| 2716 | |
---|
| 2717 | // now check all the map positions this line could intersect |
---|
| 2718 | |
---|
| 2719 | for (by=blocky1;by<=blocky2;by++,y1-=f_hi,y2-=f_hi,y_addback+=f_hi) |
---|
| 2720 | { |
---|
| 2721 | block=the_game->get_map_fg(bx,by); |
---|
| 2722 | |
---|
| 2723 | // now check the all the line segments in the block |
---|
| 2724 | foretile *f=the_game->get_fg(block); |
---|
| 2725 | block_list=f->points; |
---|
| 2726 | |
---|
| 2727 | unsigned char total=block_list->tot; |
---|
| 2728 | bdat=block_list->data; |
---|
| 2729 | unsigned char *ins=f->points->inside; |
---|
| 2730 | |
---|
[16] | 2731 | // int32_t xo=bx*tl,yo=by*th; |
---|
[2] | 2732 | for (j=0;j<total-1;j++,ins++) |
---|
| 2733 | { |
---|
| 2734 | // find the starting and ending points for this segment |
---|
| 2735 | xp1=remapx(*bdat); |
---|
| 2736 | bdat++; |
---|
| 2737 | |
---|
| 2738 | yp1=remapy(*bdat); |
---|
| 2739 | bdat++; |
---|
| 2740 | |
---|
| 2741 | xp2=remapx(*bdat); |
---|
| 2742 | yp2=remapy(bdat[1]); |
---|
| 2743 | |
---|
| 2744 | |
---|
[16] | 2745 | int32_t oy2=y2; |
---|
[2] | 2746 | if (*ins) |
---|
| 2747 | setback_intersect(checkx,y1,checkx,y2,xp1,yp1,xp2,yp2,1); |
---|
| 2748 | else |
---|
| 2749 | setback_intersect(checkx,y1,checkx,y2,xp1,yp1,xp2,yp2,-1); |
---|
| 2750 | if (oy2!=y2) |
---|
| 2751 | { |
---|
| 2752 | last_tile_hit_x=bx; |
---|
| 2753 | last_tile_hit_y=by; |
---|
| 2754 | } |
---|
| 2755 | } |
---|
| 2756 | } |
---|
| 2757 | y2+=y_addback; |
---|
| 2758 | } |
---|
| 2759 | |
---|
| 2760 | |
---|
| 2761 | |
---|
[16] | 2762 | void level::send_signal(int32_t signal) |
---|
[2] | 2763 | { |
---|
| 2764 | if (signal) // signal 0 is never sent! |
---|
| 2765 | { |
---|
| 2766 | game_object *o=first_active; |
---|
| 2767 | for (;o;o=o->next_active) |
---|
| 2768 | o->recieve_signal(signal); |
---|
| 2769 | } |
---|
| 2770 | } |
---|
| 2771 | |
---|
| 2772 | |
---|
| 2773 | int level::crush(game_object *by_who, int xamount, int yamount) |
---|
| 2774 | { |
---|
[16] | 2775 | int32_t xv,yv,crushed=0; |
---|
[2] | 2776 | game_object *o=first_active; |
---|
| 2777 | for (;o;o=o->next_active) |
---|
| 2778 | { |
---|
| 2779 | if (o->hurtable() && o!=by_who) |
---|
| 2780 | { |
---|
| 2781 | xv=-xamount; |
---|
| 2782 | yv=-yamount; |
---|
| 2783 | if (o->try_move(o->x,o->y,xv,yv,3)==by_who) |
---|
| 2784 | { |
---|
| 2785 | xv=xamount; |
---|
| 2786 | yv=yamount; |
---|
| 2787 | o->try_move(o->x,o->y,xv,yv,3); |
---|
| 2788 | if (xv==0 && yv==0) |
---|
| 2789 | { |
---|
| 2790 | if (o->state!=dead && o->state!=dieing) |
---|
| 2791 | o->do_damage(by_who->current_figure()->hit_damage,by_who,o->x,o->y,0,0); |
---|
| 2792 | |
---|
| 2793 | /* { |
---|
| 2794 | if (o->has_sequence(dieing)) |
---|
| 2795 | o->set_state(dieing); |
---|
| 2796 | else o->set_state(dead); |
---|
| 2797 | o->hp=0; |
---|
| 2798 | } */ |
---|
| 2799 | crushed=1; |
---|
| 2800 | } |
---|
| 2801 | } |
---|
| 2802 | } |
---|
| 2803 | } |
---|
| 2804 | |
---|
| 2805 | return crushed; |
---|
| 2806 | } |
---|
| 2807 | |
---|
| 2808 | |
---|
| 2809 | int level::platform_push(game_object *by_who, int xamount, int yamount) |
---|
| 2810 | { |
---|
| 2811 | int failed=0; |
---|
[16] | 2812 | int32_t xv,yv; |
---|
[2] | 2813 | game_object *o=first_active; |
---|
| 2814 | for (;o;o=o->next_active) |
---|
| 2815 | { |
---|
| 2816 | if (o->is_playable() && o->state!=dieing && o->state!=dead) |
---|
| 2817 | { |
---|
| 2818 | // check to see if the platform is going up and will run into us. |
---|
[16] | 2819 | int32_t tvx,tvy; |
---|
[2] | 2820 | if (yamount<0) |
---|
| 2821 | { |
---|
| 2822 | tvx=-xamount; |
---|
| 2823 | tvy=-yamount; |
---|
| 2824 | if (o->try_move(o->x,o->y,tvx,tvy,1)==by_who) |
---|
| 2825 | { |
---|
| 2826 | o->x+=tvx; |
---|
| 2827 | o->y+=tvy; |
---|
| 2828 | } |
---|
| 2829 | } |
---|
| 2830 | |
---|
| 2831 | /* xv=xamount; |
---|
| 2832 | yv=yamount; |
---|
| 2833 | tvx,tvy; |
---|
| 2834 | if (xv>0) tvx=xv+1; else if (xv<0) tvx=xv-1; else tvx=0; |
---|
| 2835 | if (yv>0) tvy=yv+1; else if (yv<0) tvx=yv-1; else tvy=0; |
---|
| 2836 | if (o->try_move(o->x,o->y,tvx,tvy,1)==by_who) // we the platform hit us? |
---|
| 2837 | { |
---|
| 2838 | o->x+=tvx; |
---|
| 2839 | o->y+=tvy; |
---|
| 2840 | }*/ |
---|
| 2841 | |
---|
| 2842 | xv=0; |
---|
| 2843 | yv=2; |
---|
| 2844 | if (o->try_move(o->x,o->y,xv,yv,1)==by_who) // are we standing on the platform? |
---|
| 2845 | { |
---|
| 2846 | by_who->x=-by_who->x; |
---|
| 2847 | xv=xamount; |
---|
| 2848 | yv=yamount; |
---|
| 2849 | o->try_move(o->x,o->y,xv,yv,3); |
---|
| 2850 | if (xv!=xamount || yv!=yamount) failed=1; |
---|
| 2851 | o->x+=xv; |
---|
| 2852 | o->y+=yv; |
---|
| 2853 | by_who->x=-by_who->x; |
---|
| 2854 | } |
---|
| 2855 | } |
---|
| 2856 | } |
---|
| 2857 | return !failed; |
---|
| 2858 | } |
---|
| 2859 | |
---|
| 2860 | int level::push_characters(game_object *by_who, int xamount, int yamount) |
---|
| 2861 | { |
---|
[16] | 2862 | int32_t xv,yv; |
---|
[2] | 2863 | int failed=0; |
---|
| 2864 | game_object *o=first_active; |
---|
| 2865 | for (;o;o=o->next_active) |
---|
| 2866 | { |
---|
| 2867 | if ((o->is_playable() || o->pushable()) && o->state!=dieing && o->state!=dead) |
---|
| 2868 | { |
---|
| 2869 | xv=-xamount; |
---|
| 2870 | yv=-yamount; |
---|
[16] | 2871 | int32_t tvx,tvy; |
---|
[2] | 2872 | if (xv>0) tvx=xv+1; else if (xv<0) tvx=xv-1; else tvx=0; |
---|
| 2873 | if (yv>0) tvy=yv+1; else if (yv<0) tvx=yv-1; else tvy=0; |
---|
| 2874 | if (o->try_move(o->x+xamount,o->y+yamount,tvx,tvy,3)==by_who) |
---|
| 2875 | { |
---|
| 2876 | xv=(xamount-tvx); |
---|
| 2877 | yv=(yamount-tvy); |
---|
| 2878 | o->try_move(o->x,o->y,xv,yv,3); |
---|
| 2879 | o->x+=xv; |
---|
| 2880 | o->y+=yv; |
---|
| 2881 | if (xv!=xamount-tvx || yv!=yamount-tvy) |
---|
| 2882 | failed=1; |
---|
| 2883 | } |
---|
| 2884 | } |
---|
| 2885 | } |
---|
| 2886 | return !failed; |
---|
| 2887 | } |
---|
| 2888 | |
---|
| 2889 | game_object *level::find_xrange(int x, int y, int type, int xd) |
---|
| 2890 | { |
---|
[16] | 2891 | int32_t find_ydist=100000; |
---|
[2] | 2892 | game_object *find=NULL; |
---|
| 2893 | game_object *o=first_active; |
---|
| 2894 | for (;o;o=o->next_active) |
---|
| 2895 | { |
---|
| 2896 | if (o->otype==type) |
---|
| 2897 | { |
---|
| 2898 | int x_dist=abs(x-o->x); |
---|
| 2899 | int y_dist=abs(y-o->y); |
---|
| 2900 | |
---|
| 2901 | if (x_dist<xd && y_dist<find_ydist) |
---|
| 2902 | { |
---|
| 2903 | find_ydist=y_dist; |
---|
| 2904 | find=o; |
---|
| 2905 | } |
---|
| 2906 | } |
---|
| 2907 | } |
---|
| 2908 | return find; |
---|
| 2909 | } |
---|
| 2910 | |
---|
| 2911 | |
---|
| 2912 | game_object *level::find_xclosest(int x, int y, int type, game_object *who) |
---|
| 2913 | { |
---|
[16] | 2914 | int32_t find_ydist=100000,find_xdist=0xffffff; |
---|
[2] | 2915 | game_object *find=NULL; |
---|
| 2916 | game_object *o=first_active; |
---|
| 2917 | for (;o;o=o->next_active) |
---|
| 2918 | { |
---|
| 2919 | if (o->otype==type && o!=who) |
---|
| 2920 | { |
---|
| 2921 | int x_dist=abs(x-o->x); |
---|
| 2922 | if (x_dist<find_xdist) |
---|
| 2923 | { |
---|
| 2924 | find_xdist=x_dist; |
---|
| 2925 | find_ydist=abs(y-o->y); |
---|
| 2926 | find=o; |
---|
| 2927 | } |
---|
| 2928 | else if (x_dist==find_xdist) |
---|
| 2929 | { |
---|
| 2930 | int y_dist=abs(y-o->y); |
---|
| 2931 | if (y_dist<find_ydist) |
---|
| 2932 | { |
---|
| 2933 | find_ydist=y_dist; |
---|
| 2934 | find=o; |
---|
| 2935 | } |
---|
| 2936 | } |
---|
| 2937 | } |
---|
| 2938 | } |
---|
| 2939 | return find; |
---|
| 2940 | } |
---|
| 2941 | |
---|
| 2942 | game_object *level::find_closest(int x, int y, int type, game_object *who) |
---|
| 2943 | { |
---|
[16] | 2944 | int32_t find_dist=100000; |
---|
[2] | 2945 | game_object *find=NULL; |
---|
| 2946 | game_object *o=first_active; |
---|
| 2947 | for (;o;o=o->next_active) |
---|
| 2948 | { |
---|
| 2949 | if (o->otype==type && o!=who) |
---|
| 2950 | { |
---|
| 2951 | int d=(x-o->x)*(x-o->x)+(y-o->y)*(y-o->y); |
---|
| 2952 | if (d<find_dist) |
---|
| 2953 | { |
---|
| 2954 | find=o; |
---|
| 2955 | find_dist=d; |
---|
| 2956 | } |
---|
| 2957 | } |
---|
| 2958 | } |
---|
| 2959 | return find; |
---|
| 2960 | } |
---|
| 2961 | |
---|
| 2962 | |
---|
| 2963 | |
---|
| 2964 | void level::remove_light(light_source *which) |
---|
| 2965 | { |
---|
| 2966 | if (which->known) |
---|
| 2967 | { |
---|
| 2968 | game_object *o=first; |
---|
| 2969 | for (;o;o=o->next) |
---|
| 2970 | { |
---|
| 2971 | int t=o->total_lights(); |
---|
| 2972 | int i=0; |
---|
| 2973 | for (;i<t;i++) |
---|
| 2974 | if (o->get_light(i)==which) |
---|
| 2975 | o->remove_light(o->get_light(i)); |
---|
| 2976 | } |
---|
| 2977 | } |
---|
| 2978 | delete_light(which); |
---|
| 2979 | } |
---|
| 2980 | |
---|
| 2981 | |
---|
| 2982 | game_object *level::find_type(int type, int skip) |
---|
| 2983 | { |
---|
| 2984 | game_object *l=NULL; |
---|
| 2985 | game_object *o=first; |
---|
| 2986 | for (;o;o=o->next) |
---|
| 2987 | { |
---|
| 2988 | if (o->otype==type) |
---|
| 2989 | { |
---|
| 2990 | if (!skip) |
---|
| 2991 | return o; |
---|
| 2992 | skip--; |
---|
| 2993 | l=o; |
---|
| 2994 | } |
---|
| 2995 | } |
---|
| 2996 | return l; |
---|
| 2997 | } |
---|
| 2998 | |
---|
[16] | 2999 | void level::hurt_radius(int32_t x, int32_t y,int32_t r, int32_t m, game_object *from, game_object *exclude, |
---|
[2] | 3000 | int max_push) |
---|
| 3001 | { |
---|
| 3002 | if (r<1) return ; // avoid dev vy zero |
---|
| 3003 | game_object *o=first_active; |
---|
| 3004 | for (;o;o=o->next_active) |
---|
| 3005 | { |
---|
| 3006 | if (o!=exclude && o->hurtable()) |
---|
| 3007 | { |
---|
[16] | 3008 | int32_t y1=o->y,y2=o->y-o->picture()->height(); |
---|
| 3009 | int32_t cx=abs(o->x-x),cy1=abs(y1-y),d1,d2,cy2=abs(y2-y); |
---|
[2] | 3010 | if (cx<cy1) |
---|
| 3011 | d1=cx+cy1-(cx>>1); |
---|
| 3012 | else d1=cx+cy1-(cy1>>1); |
---|
| 3013 | |
---|
| 3014 | if (cx<cy2) |
---|
| 3015 | d2=cx+cy2-(cx>>1); |
---|
| 3016 | else d2=cx+cy2-(cy2>>1); |
---|
| 3017 | if (d2<d1) |
---|
| 3018 | d1=d2; |
---|
| 3019 | |
---|
| 3020 | |
---|
| 3021 | |
---|
| 3022 | if (d1<r) |
---|
| 3023 | { |
---|
| 3024 | |
---|
| 3025 | int px=(r-cx)*max_push/r,py=(r-cy1)*max_push/r; |
---|
| 3026 | if (o->x<x) |
---|
| 3027 | px=-px; |
---|
| 3028 | if (o->y<y) |
---|
| 3029 | py=-py; |
---|
| 3030 | o->do_damage((r-d1)*m/r,from,x,y1,px,py); |
---|
| 3031 | } |
---|
| 3032 | |
---|
| 3033 | |
---|
| 3034 | } |
---|
| 3035 | } |
---|
| 3036 | |
---|
| 3037 | } |
---|
| 3038 | |
---|
| 3039 | |
---|
| 3040 | |
---|
| 3041 | game_object *level::get_random_start(int min_player_dist, view *exclude) |
---|
| 3042 | { |
---|
| 3043 | int t=0; |
---|
| 3044 | game_object *o=first; |
---|
| 3045 | for (;o;o=o->next) |
---|
| 3046 | if (o->otype==start_position_type) t++; // count how many starts there are in the level |
---|
| 3047 | |
---|
| 3048 | if (t==0) return NULL; // there aren't any starts in level! |
---|
| 3049 | |
---|
| 3050 | int retries=t; |
---|
| 3051 | do |
---|
| 3052 | { |
---|
| 3053 | int ctry=jrandom(t)+1; |
---|
| 3054 | game_object *n=first; |
---|
| 3055 | for (n=first;ctry && n;n=n->next) |
---|
| 3056 | { |
---|
| 3057 | if (n->otype==start_position_type) |
---|
| 3058 | { |
---|
| 3059 | o=n; |
---|
| 3060 | ctry--; |
---|
| 3061 | } |
---|
| 3062 | } |
---|
| 3063 | |
---|
| 3064 | int too_close=0; |
---|
| 3065 | view *v=player_list; |
---|
| 3066 | for (;v;v=v->next) |
---|
| 3067 | { |
---|
| 3068 | if (v!=exclude) |
---|
| 3069 | { |
---|
[16] | 3070 | int32_t cx=abs(v->x_center()-o->x),cy=abs(v->y_center()-o->y),d; |
---|
[2] | 3071 | if (cx<cy) |
---|
| 3072 | d=cx+cy-(cx>>1); |
---|
| 3073 | else d=cx+cy-(cy>>1); |
---|
| 3074 | if (d<min_player_dist) too_close=1; |
---|
| 3075 | } |
---|
| 3076 | } |
---|
| 3077 | if (too_close) retries--; |
---|
| 3078 | else retries=0; |
---|
| 3079 | } while (retries); |
---|
| 3080 | |
---|
| 3081 | return o; |
---|
| 3082 | } |
---|
| 3083 | |
---|
| 3084 | |
---|
| 3085 | |
---|
| 3086 | |
---|
| 3087 | |
---|
| 3088 | void level::insert_players() |
---|
| 3089 | { |
---|
| 3090 | |
---|
| 3091 | int start=0; |
---|
| 3092 | int i=0; |
---|
| 3093 | for (;i<total_objects;i++) |
---|
| 3094 | if (!strcmp(object_names[i],"START")) |
---|
| 3095 | start=i; |
---|
| 3096 | |
---|
| 3097 | view *f=player_list; |
---|
| 3098 | for (;f;f=f->next) |
---|
| 3099 | { |
---|
| 3100 | game_object *st=find_type(start,f->player_number); |
---|
| 3101 | if (st) |
---|
| 3102 | { |
---|
| 3103 | f->focus->x=st->x; |
---|
| 3104 | f->focus->y=st->y; |
---|
| 3105 | } |
---|
| 3106 | add_object_after(f->focus,st); |
---|
| 3107 | } |
---|
| 3108 | |
---|
| 3109 | } |
---|
| 3110 | |
---|
| 3111 | |
---|
| 3112 | void level::add_attacker(game_object *who) |
---|
| 3113 | { |
---|
| 3114 | if (attack_total>=attack_list_size) // see if we need to grow the list size.. |
---|
| 3115 | { |
---|
| 3116 | attack_list_size++; |
---|
| 3117 | attack_list=(game_object **)jrealloc(attack_list,sizeof(game_object *)*attack_list_size, |
---|
| 3118 | "attack_list"); |
---|
| 3119 | } |
---|
| 3120 | attack_list[attack_total]=who; |
---|
| 3121 | attack_total++; |
---|
| 3122 | } |
---|
| 3123 | |
---|
| 3124 | |
---|
| 3125 | |
---|
| 3126 | void level::add_target(game_object *who) |
---|
| 3127 | { |
---|
| 3128 | if (target_total>=target_list_size) // see if we need to grow the list size.. |
---|
| 3129 | { |
---|
| 3130 | target_list_size++; |
---|
| 3131 | target_list=(game_object **)jrealloc(target_list,sizeof(game_object *)*target_list_size, |
---|
| 3132 | "target_list"); |
---|
| 3133 | } |
---|
| 3134 | target_list[target_total]=who; |
---|
| 3135 | target_total++; |
---|
| 3136 | } |
---|
| 3137 | |
---|
| 3138 | |
---|
| 3139 | |
---|
| 3140 | void level::add_block(game_object *who) |
---|
| 3141 | { |
---|
| 3142 | if (block_total>=block_list_size) // see if we need to grow the list size.. |
---|
| 3143 | { |
---|
| 3144 | block_list_size++; |
---|
| 3145 | block_list=(game_object **)jrealloc(block_list,sizeof(game_object *)*block_list_size, |
---|
| 3146 | "block_list"); |
---|
| 3147 | } |
---|
| 3148 | block_list[block_total]=who; |
---|
| 3149 | block_total++; |
---|
| 3150 | } |
---|
| 3151 | |
---|
| 3152 | |
---|
| 3153 | void level::add_all_block(game_object *who) |
---|
| 3154 | { |
---|
| 3155 | if (all_block_total>=all_block_list_size) // see if we need to grow the list size.. |
---|
| 3156 | { |
---|
| 3157 | all_block_list_size++; |
---|
| 3158 | all_block_list=(game_object **)jrealloc(all_block_list,sizeof(game_object *)*all_block_list_size, |
---|
| 3159 | "all_block_list"); |
---|
| 3160 | } |
---|
| 3161 | all_block_list[all_block_total]=who; |
---|
| 3162 | all_block_total++; |
---|
| 3163 | } |
---|
| 3164 | |
---|
| 3165 | |
---|
[16] | 3166 | game_object *level::find_object_in_area(int32_t x, int32_t y, int32_t x1, int32_t y1, int32_t x2, int32_t y2, |
---|
[2] | 3167 | Cell *list, game_object *exclude) |
---|
| 3168 | { |
---|
| 3169 | game_object *closest=NULL; |
---|
[16] | 3170 | int32_t closest_distance=0xfffffff,distance,xo,yo; |
---|
[2] | 3171 | game_object *o=first_active; |
---|
| 3172 | for (;o;o=o->next_active) |
---|
| 3173 | { |
---|
[16] | 3174 | int32_t xp1,yp1,xp2,yp2; |
---|
[2] | 3175 | o->picture_space(xp1,yp1,xp2,yp2); |
---|
| 3176 | |
---|
| 3177 | |
---|
| 3178 | if (!(xp1>x2 || xp2<x1 || yp1>y2 || yp2<y1) && o!=exclude) |
---|
| 3179 | { |
---|
| 3180 | // check to see if the type is in the list |
---|
| 3181 | Cell *v=list; |
---|
| 3182 | for (;!NILP(v) && lnumber_value(CAR(v))!=o->otype;v=CDR(v)); |
---|
| 3183 | if (!NILP(v)) |
---|
| 3184 | { |
---|
| 3185 | xo=abs(o->x-x); |
---|
| 3186 | yo=abs(o->y-y); |
---|
| 3187 | distance=xo*xo+yo*yo; |
---|
| 3188 | if (distance<closest_distance) |
---|
| 3189 | { |
---|
| 3190 | closest_distance=distance; |
---|
| 3191 | closest=o; |
---|
| 3192 | } |
---|
| 3193 | } |
---|
| 3194 | } |
---|
| 3195 | } |
---|
| 3196 | return closest; |
---|
| 3197 | } |
---|
| 3198 | |
---|
| 3199 | |
---|
| 3200 | |
---|
| 3201 | |
---|
[16] | 3202 | game_object *level::find_object_in_angle(int32_t x, int32_t y, int32_t start_angle, int32_t end_angle, |
---|
[2] | 3203 | void *list, game_object *exclude) |
---|
| 3204 | { |
---|
| 3205 | game_object *closest=NULL; |
---|
[16] | 3206 | int32_t closest_distance=0xfffffff,distance,xo,yo; |
---|
[2] | 3207 | game_object *o=first_active; |
---|
| 3208 | for (;o;o=o->next_active) |
---|
| 3209 | { |
---|
[16] | 3210 | int32_t angle=lisp_atan2(o->y-y,o->x-x); |
---|
[2] | 3211 | if (((start_angle<=end_angle && (angle>=start_angle && angle<=end_angle)) |
---|
| 3212 | || (start_angle>end_angle && (angle>=start_angle || angle<=end_angle))) |
---|
| 3213 | && o!=exclude) |
---|
| 3214 | { |
---|
| 3215 | // check to see if the type is in the list |
---|
| 3216 | Cell *v=(Cell *)list; |
---|
| 3217 | for (;!NILP(v) && lnumber_value(CAR(v))!=o->otype;v=CDR(v)); |
---|
| 3218 | if (!NILP(v)) |
---|
| 3219 | { |
---|
| 3220 | xo=abs(o->x-x); |
---|
| 3221 | yo=abs(o->y-y); |
---|
| 3222 | distance=xo*xo+yo*yo; |
---|
| 3223 | if (distance<closest_distance) |
---|
| 3224 | { |
---|
| 3225 | closest_distance=distance; |
---|
| 3226 | closest=o; |
---|
| 3227 | } |
---|
| 3228 | } |
---|
| 3229 | } |
---|
| 3230 | } |
---|
| 3231 | return closest; |
---|
| 3232 | } |
---|
| 3233 | |
---|
| 3234 | |
---|
| 3235 | object_node *level::make_not_list(object_node *list) |
---|
| 3236 | { |
---|
| 3237 | object_node *f=NULL,*l=NULL; |
---|
| 3238 | game_object *o=first; |
---|
| 3239 | for (;o;o=o->next) |
---|
| 3240 | { |
---|
| 3241 | if (!object_to_number_in_list(o,list)) |
---|
| 3242 | { |
---|
| 3243 | object_node *q=new object_node(o,NULL); |
---|
| 3244 | if (f) |
---|
| 3245 | l->next=q; |
---|
| 3246 | else f=q; |
---|
| 3247 | l=q; |
---|
| 3248 | } |
---|
| 3249 | } |
---|
| 3250 | return f; |
---|
| 3251 | } |
---|
| 3252 | |
---|
| 3253 | void level::write_object_info(char *filename) |
---|
| 3254 | { |
---|
| 3255 | FILE *fp=open_FILE(filename,"wb"); |
---|
| 3256 | if (fp) |
---|
| 3257 | { |
---|
| 3258 | int i=0; |
---|
| 3259 | game_object *o=first; |
---|
| 3260 | for (;o;o=o->next) |
---|
| 3261 | { |
---|
[16] | 3262 | fprintf(fp,"%3d %s %4ld %4ld %4ld %4ld %04d\n",i++,object_names[o->otype],(long)o->x,(long)o->y, |
---|
| 3263 | (long)o->xvel(),(long)o->yvel(),o->current_frame); |
---|
[2] | 3264 | } |
---|
| 3265 | fclose(fp); |
---|
| 3266 | } |
---|
| 3267 | } |
---|
| 3268 | |
---|
| 3269 | |
---|
[16] | 3270 | area_controller::area_controller(int32_t X, int32_t Y, int32_t W, int32_t H, area_controller *Next) |
---|
[2] | 3271 | { |
---|
| 3272 | x=X; y=Y; w=W; h=H; |
---|
| 3273 | next=Next; active=0; |
---|
| 3274 | |
---|
| 3275 | ambient=-1; |
---|
| 3276 | view_xoff=-1; |
---|
| 3277 | view_yoff=-1; |
---|
| 3278 | ambient_speed=2; |
---|
| 3279 | view_xoff_speed=4; |
---|
| 3280 | view_yoff_speed=4; |
---|
| 3281 | } |
---|