/* Copyright (C) 1995-2002 FSGames. Ported by Sean Ford and Yan Shosh * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // // weap; a derived class of walker // #include "graph.h" #include "smooth.h" weap::weap(unsigned char *data, screen *myscreen) : walker(data, myscreen) { do_bounce = 0; // don't normally bounce :) } weap::~weap() { //buffers: PORT: can't call destructor w/o obj: walker::~walker(); } short weap::act() { static char message[80]; // Make sure everyone we're poshorting to is valid if (foe && foe->dead) foe = NULL; if (leader && leader->dead) leader = NULL; if (owner && owner->dead) owner = NULL; if (!owner) owner = this; //to fix cases where our parent died! collide_ob = NULL; // always start with no collison.. // Complete previous animations (like firing) if (ani_type != ANI_WALK) return animate(); // printf("weap %d is ani %d\n", family, ani_type); if (mysmoother->query_genre_x_y(xpos, ypos) == TYPE_TREES) if (lineofsight) lineofsight--; switch (act_type) { // We are the control character case ACT_CONTROL: { printf("Weapon is act_control?\n"); return 1; } case ACT_SIT: // for things like trees { if (family != FAMILY_TREE && family != FAMILY_BLOOD && family != FAMILY_DOOR) //printf("weapon sitting\n"); myscreen->do_notify("Weapon sitting", this); return 1; } // We are a generator case ACT_GENERATE: { printf("Weapon is act_generate?\n"); //act_generate(); break; } // We are a weapon case ACT_FIRE: { act_fire(); return 1; //break; } case ACT_GUARD: { printf("Weapon on guard mode?\n"); // act_guard(); break; } case ACT_DIE: { this->dead = 1; return 1; } // We are randomly walking toward enemy case ACT_RANDOM: { sprintf(message, "Weapon %d doing act random?", family); //printf("Weapon doing act_random?\n"); myscreen->do_notify(message, this); return 1; } // END RANDOM //break; default: { //printf("No act type set for weapon.\n"); myscreen->do_notify("No act type set for weapon", this); return 0; } } // END SWITCH return 0; } // death is called when an object dies (weapon destructed, etc.) // for special effects .. short weap::death() { // Note that the 'dead' variable should ALREADY be set by the // time this function is called, so that we can easily reverse // the decision :) walker *newob = NULL; if (death_called) // Make sure we don't get multiple deaths return 0; death_called = 1; switch (family) { case FAMILY_KNIFE: // for returning knife if (owner && owner->query_family() != FAMILY_SOLDIER) break; // only soldiers get returning knives newob = screenp->add_ob(ORDER_FX, FAMILY_KNIFE_BACK); newob->owner = owner; newob->center_on(this); newob->lastx = lastx; newob->lasty = lasty; newob->stepsize = stepsize; newob->ani_type = ANI_ATTACK; newob->damage = damage; break; // end of soldier returning knife case FAMILY_ROCK: // used for the elf's bouncing rock, etc. if (!do_bounce || !lineofsight || collide_ob) // died of natural causes break; dead = 0; // first, un-dead us so we can collide .. // Did we hit a barrier? if (screenp->query_grid_passable(xpos+lastx, ypos+lasty, this)) { dead = 1; break; // if not, die like normal } if (screenp->query_grid_passable(xpos-lastx, ypos+lasty, this)) { setxy(xpos-lastx, ypos+lasty); // bounce 'down-left' lastx = -lastx; death_called = 0; break; } if (screenp->query_grid_passable(xpos+lastx, ypos-lasty, this)) { setxy(xpos+lastx, ypos-lasty); // bounce 'up-right' lasty = -lasty; death_called = 0; break; } if (screenp->query_grid_passable(xpos-lastx, ypos-lasty, this)) { setxy(xpos-lastx, ypos-lasty); lastx = -lastx; lasty = -lasty; death_called = 0; break; } // Else we're really stuck, so die :) dead = 1; break; case FAMILY_FIRE_ARROW: // only for exploding, really case FAMILY_BOULDER: if (!skip_exit) break; // skip_exit means we're supposed to explode :) if (!owner || owner->dead) owner = this; newob = screenp->add_ob(ORDER_FX, FAMILY_EXPLOSION, 1); if (!newob) break; // failsafe if (on_screen()) screenp->soundp->play_sound(SOUND_EXPLODE); newob->owner = owner; newob->stats->hitpoints = 0; newob->stats->level = owner->stats->level; newob->ani_type = ANI_EXPLODE; newob->center_on(this); newob->damage = damage*2; break; // end fire (exploding) arrows case FAMILY_WAVE: // grow to wave2 dead = 0; transform_to(ORDER_WEAPON, FAMILY_WAVE2); stats->hitpoints = stats->max_hitpoints; break; // end wave -> wave2 case FAMILY_WAVE2: // grow to wave3 dead = 0; transform_to(ORDER_WEAPON, FAMILY_WAVE3); stats->hitpoints = stats->max_hitpoints; break; // end wave2 -> wave3 case FAMILY_DOOR: // display open picture newob = screenp->add_weap_ob(ORDER_FX, FAMILY_DOOR_OPEN); if (!newob) break; newob->ani_type = ANI_DOOR_OPEN; newob->setxy(xpos, ypos); newob->stats->level = stats->level; newob->team_num = team_num; // newob->ignore = 1; // What way are we 'facing'? if (mysmoother->query_genre_x_y((xpos/GRID_SIZE),(ypos/GRID_SIZE)-1) == TYPE_WALL) // a wall above us? { newob->curdir = FACE_RIGHT; // newob->setxy(xpos, ypos-12); // and move us 'up' } else { curdir = FACE_UP; } break; // end open the door .. default: break; } return 1; } short weap::animate() { //walker * newob; // We never use ani_type as as I can tell; always use 0 // if (ani_type) // { // printf("weap ani_type = %d\n", ani_type); // ani_type = 0; // } switch (family) { case FAMILY_TREE: case FAMILY_BLOOD: if (ani_type > 1) ani_type = 0; set_frame(ani[curdir+ani_type*NUM_FACINGS][cycle]); cycle++; if (ani[curdir+ani_type*NUM_FACINGS][cycle] == -1) { ani_type = 0; //ANI_WALK; cycle = 0; } break; case FAMILY_CIRCLE_PROTECTION: if (!owner || owner->dead || stats->hitpoints < 1) { dead = 1; return death(); } center_on(owner); break; case FAMILY_GLOW: if (ani_type > 2) // illegal case ani_type = 2; // pulse case set_frame(ani[curdir+ani_type*NUM_FACINGS][cycle]); cycle++; if (ani[curdir+ani_type*NUM_FACINGS][cycle] == -1) { ani_type = 2; // pulse cycle = 0; } if (lifetime-- < 1) { dead = 1; death(); } break; default: ani_type = 0; set_frame(ani[curdir][cycle]); cycle++; if (ani[curdir][cycle] == -1) { cycle = 0; } break; } // end of family switch return 1; } short weap::setxy(short x, short y) { return walker::setxy(x, y); }