示例#1
0
void move_object(int i, int16_t x, int16_t y)
{
    if (object[i].draw_index < 255) // object was visible...
    {
        if (on_screen(x, y))
        {
            // object is still visible, need to sort draw_order.. but do it later!
            object[i].iy = y - tile_map_y;
            object[i].ix = x - tile_map_x;
        }
        else // object is no longer visible
        {
            for (int k=object[i].draw_index+1; k<drawing_count; ++k)
            {
                // move the pointers around for the objects draw_index:
                // object at draw_order k should go to spot k-1:
                int object_k = draw_order[k];
                // move down draw_order:
                object[object_k].draw_index = k-1;
                draw_order[k-1] = object_k;
            }
            object[i].iy = SCREEN_H;
            object[i].ix = SCREEN_W;
            object[i].draw_index = -1;
            --drawing_count;
        }
    }
    else // wasn't visible
    {
        if (on_screen(x, y))
        {
            // object has become visible
            make_unseen_object_viewable(i);
        }
        else // object is still not visible
        {
            // do nothing!
        }
    }
    object[i].y = y;
    object[i].x = x;
}
示例#2
0
void MonsterController::post_draw(GameState* gs) {
	PlayerInst* player = gs->local_player();
	if (!player) {
		return;
	}
	EnemyInst* target = (EnemyInst*)gs->get_instance(player->target());
	if (!target) {
		return;
	}

	ldraw::draw_circle_outline(COL_GREEN.alpha(140),
			on_screen(gs, target->ipos()), target->target_radius + 5, 2);
}
示例#3
0
int create_object(int sprite_draw_index, int16_t x, int16_t y, uint8_t z)
{
    if (object_count >= MAX_OBJECTS)
        return -1;

    int i = first_free_object;
    // setup head of list for both free and used: 
    first_free_object = object[i].next_free_object;
    object[i].next_used_object = first_used_object;
    first_used_object = i;

    // add in object properties
    object[i].y = y;
    object[i].x = x;
    object[i].z = z;
    if (on_screen(object[i].x, object[i].y))
        make_unseen_object_viewable(i);
    else
        object[i].draw_index = -1;

    object[i].sprite_index = sprite_draw_index;
    ++object_count;
    return i;
}
示例#4
0
short treasure::eat_me(walker  * eater)
{
	short guys_here;
	oblink *here;
	static text eattext(screenp);
	char message[80];
	Sint32 distance;
	walker  *target, *flash;
	static char exitname[40];
	Sint32 leftside, rightside;

	switch (family)
	{
		case FAMILY_DRUMSTICK:
			if (eater->stats->hitpoints >= eater->stats->max_hitpoints)
				return 1;
			else
			{
				eater->stats->hitpoints += (short) ((10*stats->level) + (short) random((short) 10*stats->level));
				if (eater->stats->hitpoints > eater->stats->max_hitpoints)
					eater->stats->hitpoints = eater->stats->max_hitpoints;
				dead = 1;
				if (on_screen())
					screenp->soundp->play_sound(SOUND_EAT);
				return 1;
			}
		case FAMILY_GOLD_BAR:
			if (eater->team_num == 0 || eater->myguy)
			{
				myscreen->m_score[eater->team_num] += (200*stats->level);
				dead = 1;
				if (on_screen())
					screenp->soundp->play_sound(SOUND_MONEY);
			}
			return 1;
		case FAMILY_SILVER_BAR:
			if (eater->team_num == 0 || eater->myguy)
			{
				myscreen->m_score[eater->team_num] += (50*stats->level);
				dead = 1;
				if (on_screen())
					screenp->soundp->play_sound(SOUND_MONEY);
			}
			return 1;
		case FAMILY_FLIGHT_POTION:
			if (!eater->stats->query_bit_flags(BIT_FLYING) )
			{
				eater->flight_left += (150*stats->level);
				if (eater->user != -1)
				{
					sprintf(message, "Potion of Flight(%d)!", stats->level);
					screenp->do_notify(message, eater);
				}
				dead = 1;
			}
			return 1;
		case FAMILY_MAGIC_POTION:
			if (eater->stats->magicpoints < eater->stats->max_magicpoints)
				eater->stats->magicpoints = eater->stats->max_magicpoints;
			eater->stats->magicpoints += (50*stats->level);
			dead = 1;
			if (eater->user != -1)
			{
				sprintf(message, "Potion of Mana(%d)!", stats->level);
				screenp->do_notify(message, eater);
			}
			return 1;
		case FAMILY_INVULNERABLE_POTION:
			if (!eater->stats->query_bit_flags(BIT_INVINCIBLE) )
			{
				eater->invulnerable_left += (150*stats->level);
				dead = 1;
				if (eater->user != -1)
				{
					sprintf(message, "Potion of Invulnerability(%d)!", stats->level);
					screenp->do_notify(message, eater);
				}
			}
			return 1;
		case FAMILY_INVIS_POTION:
			eater->invisibility_left += (150*stats->level);
			if (eater->user != -1)
			{
				sprintf(message, "Potion of Invisibility(%d)!", stats->level);
				screenp->do_notify(message, eater);
			}
			dead = 1;
			return 1;
		case FAMILY_SPEED_POTION:
			eater->speed_bonus_left += 50*stats->level;
			eater->speed_bonus = stats->level;
			if (eater->user != -1)
			{
				sprintf(message, "Potion of Speed(%d)!", stats->level);
				screenp->do_notify(message, eater);
			}
			dead = 1;
			return 1;
		case FAMILY_EXIT: // go to another level, possibly
			if (eater->in_act) return 1;
			if (eater->query_act_type()!= ACT_CONTROL || (eater->skip_exit > 1))
				return 1;
			eater->skip_exit = 10;
			// See if there are any enemies left ...
			if (screenp->level_done == 0)
				guys_here = 1;
			else
				guys_here = 0;
			// Get the name of our exit..
			sprintf(message, "scen%d", stats->level);
			strcpy(exitname, myscreen->get_scen_title(message, myscreen) );

			//buffers: PORT: using strcmp instead of stricmp
			if (!strcmp(exitname, "none"))
				sprintf(exitname, "Level %d", stats->level);

			leftside  = 160 - ( (strlen(exitname) + 18) * 3);
			rightside = 160 + ( (strlen(exitname) + 18) * 3);
			// First check to see if we're withdrawing into
			//    somewhere we've been, in which case we abort
			//    this level, and set our current level to
			//    that pointed to by the exit ...
			if ( screenp->is_level_completed(stats->level)
			        && !screenp->is_level_completed(screenp->scen_num)
			        && (guys_here != 0)
			   ) // okay to leave
			{
				leftside -= 12;
				rightside += 12;
                
                char buf[40];
                snprintf(buf, 40, "Withdraw to %s?", exitname);
                bool result = yes_or_no_prompt("Exit Field", buf, false);
				// Redraw screen ..
				screenp->redrawme = 1;

				if (result) // accepted level change
				{
					clear_keyboard();
					// Delete all of our current information and abort ..
					here = myscreen->oblist;
					while (here)
					{
						if (here->ob && here->ob->query_order() == ORDER_LIVING)
						{
							//myscreen->remove_ob(here->ob);
							here->ob->dead = 1;
							myscreen->myobmap->remove
							(here->ob);
							//myscreen->remove_obmap(here->ob);
						}
						here = here->next;
					}
					//here = myscreen->fxlist;
					//while (here)
					//{
					//  if (here->ob)
					//    myscreen->remove_fx_ob(here->ob);
					//  here = here->next;
					//}
					// Now load the game as it was ...
					load_saved_game("save0", myscreen);
					myscreen->scen_num = (short) (stats->level-1);
					myscreen->end = 1;
					save_game("save0", myscreen);
					retreat = 1;

					return screenp->endgame(1, stats->level); // retreat
				}  // end of accepted withdraw to new level ..
				clear_keyboard();
			} // end of checking for withdrawal to completed level

			//buffers: also, allow exit if scenario_type == can exit
			if (!guys_here || (screenp->scenario_type == SCEN_TYPE_CAN_EXIT)) // nobody evil left, so okay to exit level ..
			{
                char buf[40];
                snprintf(buf, 40, "Exit to %s?", exitname);
                bool result = yes_or_no_prompt("Exit Field", buf, false);
				// Redraw screen ..
				screenp->redrawme = 1;

				if(result) // accepted level change
				{
					clear_keyboard();
					//screenp->levelstatus[screenp->scen_num] = 1;
					return screenp->endgame(0, stats->level);
				}
				clear_keyboard();
				return 1;
			}
			return 1;
		case FAMILY_TELEPORTER:
			if (eater->skip_exit > 1)
				return 1;
			distance = distance_to_ob_center(eater); // how  away?
			if (distance > 21)
				return 1;
			if (distance < 4 && eater->skip_exit)
			{
				//eater->skip_exit++;
				eater->skip_exit = 8;
				return 1;
			}
			// If we're close enough, teleport ..
			eater->skip_exit += 20;
			if (!leader)
				target = find_teleport_target();
			else
				target = leader;
			if (!target)
				return 1;
			leader = target;
			eater->center_on(target);
			if (!screenp->query_passable(eater->xpos, eater->ypos, eater))
			{
				eater->center_on(this);
				return 1;
			}
			// Now do special effects
			flash = screenp->add_ob(ORDER_FX, FAMILY_FLASH);
			flash->ani_type = ANI_EXPAND_8;
			flash->center_on(this);
			return 1;
		case FAMILY_LIFE_GEM: // get back some of lost man's xp ..
			if (eater->team_num != team_num) // only our team can get these
				return 1;
			myscreen->m_score[eater->team_num] += stats->hitpoints;
			flash = screenp->add_ob(ORDER_FX, FAMILY_FLASH);
			flash->ani_type = ANI_EXPAND_8;
			flash->center_on(this);
			dead = 1;
			death();
			return 1;
		case FAMILY_KEY: // get the key to this door ..
			if (!(eater->keys & (Sint32)(pow((double) 2, stats->level)) )) // just got it?
			{
				eater->keys |= (Sint32) (pow((double)2, stats->level)); // ie, 2, 4, 8, 16...
				if (eater->myguy)
					sprintf(message, "%s picks up key %d", eater->myguy->name,
					        stats->level);
				else
					sprintf(message, "%s picks up key %d", eater->stats->name, stats->level);
				if (eater->team_num == 0) // only show players picking up keys
				{
					myscreen->do_notify(message, eater);
					if (eater->on_screen())
						myscreen->soundp->play_sound(SOUND_MONEY);
				}
			}
			return 1;
		default:
			return 1;
	} // end of treasure-check
}
示例#5
0
// death is called when an object dies (or weapon destructed, etc.)
// for special effects ..
short effect::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 :)
	oblink *scarelist, *here;
	oblink *frylist; // for the thief's bombs :)
	short howmany = 0;
	walker  *newob;
	Sint32 xdelta,ydelta;
	Sint32 tempx, tempy, generic;

	if (death_called)
		return 0;
	death_called = 1;

	switch (family)
	{
		case FAMILY_GHOST_SCARE: // the ghost's scare
			if (!owner || owner->dead)
				return 0;
			scarelist = screenp->find_foes_in_range(screenp->oblist, 50+(10*owner->stats->level),
			                                        &howmany, owner);
			if (howmany < 1)
				return 0;

			here = scarelist;
			while (here)
			{
				if (here->ob && here->ob->query_order() == ORDER_LIVING)
				{
					tempx = here->ob->xpos - xpos;
					if (tempx)
						tempx = tempx / (abs(tempx));
					tempy = here->ob->ypos - ypos;
					if (tempy)
						tempy = tempy / (abs(tempy));
					generic = (owner->stats->level*25);
					if (here->ob->myguy)
						generic -= random(here->ob->myguy->constitution);
					if (generic > 0)
						here->ob->stats->force_command(COMMAND_WALK,
						                               (short) generic, (short) tempx, (short) tempy);
				} // end of valid target
				here = here->next;
			} // end of cycle through scare list
			delete_list(scarelist);
			break;  // end of ghost scare
		case FAMILY_BOMB: // Burning bomb
			if (!owner || owner->dead)
				owner = this;
			if (on_screen())
				screenp->soundp->play_sound(SOUND_EXPLODE);
			newob = screenp->add_ob(ORDER_FX, FAMILY_EXPLOSION, 1);
			newob->owner = owner;
			newob->stats->hitpoints = 0;
			newob->stats->level = owner->stats->level;
			newob->ani_type = ANI_EXPLODE;
			//newob->setxy(xpos, ypos);
			newob->center_on(this);
			newob->damage = damage;
			break;

		case FAMILY_EXPLOSION: // the bomb's explosion
			if (!owner || owner->dead)
				owner = this;
			// Set the max distance for a bomb ..
			generic = 4*owner->stats->level;
			if (generic > 96) // set max range to about 6 tiles
				generic = 96;
			if (skip_exit) // magical, ie mage, don't go far ..
			{
				generic = 16;
			}
			frylist = screenp->find_in_range(screenp->oblist, 15+generic,
			                                 &howmany, this);
			//Log("got in range, %d\n", howmany);
			// Damage our tile location ..
			screenp->damage_tile( (short) (xpos+(sizex/2)), (short) (ypos+(sizey/2)) );
			if (howmany < 1)
				return 0;
			// Set our team number to garbage so we can hurt everyone
			//team_num = 50;
			here = frylist;
			while (here)
			{
				if (here->ob && !here->ob->dead &&
				        (here->ob->query_order() != ORDER_TREASURE) &&
				        (here->ob->query_order() != ORDER_FX) &&
				        (!skip_exit || here->ob != owner)
				   ) //&&
					//       here->ob->query_order() == ORDER_LIVING
					//     && here->ob->team_num != owner->team_num
					//      )
				{
					//shove the target
					xdelta = here->ob->xpos - xpos;
					if (xdelta)
						xdelta = xdelta/abs(xdelta);
					ydelta = here->ob->ypos - ypos;
					if (ydelta)
						ydelta = ydelta/abs(ydelta);
					// Set the distance to 'shove' by explosion
					generic = 2+owner->stats->level/15;
					if (generic > 8) // max of about 8 steps
						generic = 8;
					here->ob->stats->force_command(COMMAND_WALK,generic,(short)xdelta,(short)ydelta);
					// Damage (attack) the object
					if (here->ob == owner) // do less damage
					{
						damage /= 4;
						attack(here->ob);
						damage *= 4;
					}
					else if (!owner->dead && owner->is_friendly(here->ob))
					{
						damage /= 2;
						attack(here->ob);
						damage *= 2;
					}
					else
						attack(here->ob);
				}
				here = here->next;
			}
			break;  // end explosion case
		default:
			break;
	}                    // end of switch family for effect objects

	return 1;
}
示例#6
0
short effect::act()
{
	short temp;
	Sint32 xd, yd, distance, generic;
	oblink *foelist, *here;
	walker *newob;
	short numfoes;

	// 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;

	collide_ob = NULL; // always start with no collison..

	// Any special actions ..
	switch (family) // determine what to do..
	{
		case FAMILY_GHOST_SCARE:
			if (owner)
				center_on(owner);
			break;
		case FAMILY_MAGIC_SHIELD: // revolve around owner
			if (!owner || owner->dead)
			{
				dead = 1;
				death();
				break;
			}
			switch (drawcycle % 16)
			{
				case 0:
					xd = 0;
					yd = -24;
					break;
				case 1:
					xd = -9;
					yd = -22;
					break;
				case 2:
					xd = -17;
					yd = -17;
					break;
				case 3:
					xd = -22;
					yd = -9;
					break;

				case 4:
					xd = -24;
					yd = 0;
					break;
				case 5:
					xd = -22;
					yd = 9;
					break;
				case 6:
					xd = -17;
					yd = 17;
					break;
				case 7:
					xd = -9;
					yd = 22;
					break;

				case 8:
					xd = 0;
					yd = 24;
					break;
				case 9:
					xd = 9;
					yd = 22;
					break;
				case 10:
					xd = 17;
					yd = 17;
					break;
				case 11:
					xd = 22;
					yd = 9;
					break;

				case 12:
					xd = 24;
					yd = 0;
					break;
				case 13:
					xd = 22;
					yd = -9;
					break;
				case 14:
					xd = 17;
					yd = -17;
					break;
				case 15:
					xd = 9;
					yd = -22;
					break;
			}
			center_on(owner);
			setxy( (short)( xpos+xd ), (short) (ypos+yd) );
			foelist = screenp->find_foe_weapons_in_range(
			              screenp->oblist, sizex, &temp, this);
			here = foelist;
			while (foelist)  // first weapons
			{
				stats->hitpoints -= foelist->ob->damage;
				foelist->ob->dead = 1;
				foelist->ob->death();
				foelist = foelist->next;
			}
			delete_list(here);
			foelist = screenp->find_foes_in_range(
			              screenp->oblist, sizex, &temp, this);
			here = foelist;
			while (foelist) // second enemies
			{
				stats->hitpoints -= foelist->ob->damage;
				attack(foelist->ob);
				dead = 0;
				foelist = foelist->next;
			}
			delete_list(here);
			if ( (stats->hitpoints <= 0) || (lifetime-- < 0) )
			{
				dead = 1;
				death();
			}
			break; // end of magic shield case
		case FAMILY_BOOMERANG: // fighter's boomerang
			// Zardus: FIX: if the drawcycle is in its >253s, the boomerang dies. This will fix the bug where
			// the boomerang comes back to 0 (owner) after spiraling around all the way if the owner has
			// that good of an ability (to keep its life so high). This caps boomerang ability, though... Another
			// fix could be to make the drawcycle var an int or at least something with more capacity than char.
			if (!owner || owner->dead || drawcycle > 253)
			{
				dead = 1;
				death();
				break;
			}
			switch (drawcycle % 16)
			{
				case 0:
					xd = 0;
					yd = -24;
					break;
				case 1:
					xd = -9;
					yd = -22;
					break;
				case 2:
					xd = -17;
					yd = -17;
					break;
				case 3:
					xd = -22;
					yd = -9;
					break;

				case 4:
					xd = -24;
					yd = 0;
					break;
				case 5:
					xd = -22;
					yd = 9;
					break;
				case 6:
					xd = -17;
					yd = 17;
					break;
				case 7:
					xd = -9;
					yd = 22;
					break;

				case 8:
					xd = 0;
					yd = 24;
					break;
				case 9:
					xd = 9;
					yd = 22;
					break;
				case 10:
					xd = 17;
					yd = 17;
					break;
				case 11:
					xd = 22;
					yd = 9;
					break;

				case 12:
					xd = 24;
					yd = 0;
					break;
				case 13:
					xd = 22;
					yd = -9;
					break;
				case 14:
					xd = 17;
					yd = -17;
					break;
				case 15:
					xd = 9;
					yd = -22;
					break;
			}
			xd *= (drawcycle+4);
			xd /= 48;
			yd *= (drawcycle+4);
			yd /= 48;
			center_on(owner);
			setxy((short) (xpos+xd), (short) (ypos+yd) );
			foelist = screenp->find_foe_weapons_in_range(
			              screenp->oblist, sizex*2, &temp, this);
			here = foelist;
			while (foelist)  // first weapons
			{
				stats->hitpoints -= foelist->ob->damage;
				foelist->ob->dead = 1;
				foelist->ob->death();
				foelist = foelist->next;
			}
			delete_list(here);
			foelist = screenp->find_foes_in_range(
			              screenp->oblist, sizex, &temp, this);
			here = foelist;
			while (foelist) // second enemies
			{
				stats->hitpoints -= foelist->ob->damage;
				attack(foelist->ob);
				dead = 0;
				foelist = foelist->next;
			}
			delete_list(here);
			if ( (stats->hitpoints <= 0) || (lifetime-- < 0) )
			{
				dead = 1;
				death();
			}
			break; // end of boomerang case
		case FAMILY_KNIFE_BACK: // returning blade
			if (!owner || owner->dead)
			{
				dead = 1;
				break;
			}
			distance = distance_to_ob(owner);
			if (distance > 10)
			{
				xd = yd = 0; // zero out distance movements
				if (owner->xpos > xpos)
				{
					if ( (owner->xpos - xpos) > stepsize )
						xd = stepsize;
					else
						xd = owner->xpos - xpos;
				}
				else if (owner->xpos < xpos)
				{
					if ( (xpos - owner->xpos) > stepsize )
						xd = -stepsize;
					else
						xd = owner->xpos - xpos;
				}
				if (owner->ypos > ypos)
				{
					if ( (owner->ypos - ypos) > stepsize )
						yd = stepsize;
					else
						yd = owner->ypos - ypos;
				}
				else if (owner->ypos < ypos)
				{
					if ( (ypos - owner->ypos) > stepsize )
						yd = -stepsize;
					else
						yd = owner->ypos - ypos;
				}
				setxy((short) (xpos+xd), (short) (ypos+yd) );
				newob = screenp->add_ob(ORDER_WEAPON, FAMILY_KNIFE);
				newob->damage = damage;
				newob->owner = owner;
				newob->team_num = team_num;
				newob->death_called = 1; // to ensure no spawning of more ..
				newob->setxy(xpos, ypos);
				if (!screenp->query_object_passable((short) (xpos+xd), (short) (ypos+yd), newob))
				{
					newob->attack(newob->collide_ob);
					damage /= 4;
					//setxy(xpos-(2*xd)+random(xd), ypos-(2*yd)+random(yd));
				}
				newob->dead = 1;
			}
			else
			{
				owner->weapons_left++;
				//if (owner->user != -1)
				//{
				//  sprintf(message, "Knives now %d", owner->weapons_left);
				//  screenp->do_notify(message, owner);
				//}
				ani_type = ANI_WALK;
				dead = 1;
			}
			break;
		case FAMILY_CLOUD: // poison cloud
			if (lifetime > 0)
				lifetime--;
			else
			{
				dead = 1;
				death();
			}
			if (lifetime < 8)
				invisibility_left +=3;
			if (invisibility_left > 0)
				invisibility_left--;
			// Hit any nearby foes (not friends, for now)
			foelist = screenp->find_foes_in_range(
			              screenp->oblist, sizex, &temp, this);
			here = foelist;
			while (foelist) //
			{
				if (hits(xpos, ypos, sizex, sizey, // this is the cloud
				         foelist->ob->xpos, foelist->ob->ypos,
				         foelist->ob->sizex, foelist->ob->sizey)
				   )
				{
					attack(foelist->ob);
				} // end of actual hit
				foelist = foelist->next;
			}
			delete_list(here);
			// Are we performing some action?
			if (stats->commandlist)
				temp = stats->do_command();
			else
			{
				xd = yd = 0;
				while (xd == 0 && yd == 0)
				{
					xd = random(3)-1;
					yd = random(3)-1;
				}
				stats->add_command(COMMAND_WALK, (short) random(20), (short) xd, (short) yd);
			}
			break; // end of cloud
		case FAMILY_CHAIN: // chain lightning ..
			if (!leader || lineofsight<1 || !owner) // lost our leader, etc.? kill us ..
			{
				dead = 1;
				death();
				return 1;
			}
			// Are we at our leader? If so, attack him :)
			if (hits(xpos, ypos, sizex, sizey,
			         leader->xpos, leader->ypos, leader->sizex, leader->sizey))
			{
				// Do things ..
				newob = screenp->add_ob(ORDER_FX, FAMILY_EXPLOSION);
				if (!newob)
				{
					dead = 1;
					death();
					return 1; // failsafe
				}
				newob->owner = owner;
				newob->team_num = team_num;
				newob->stats->level = stats->level;
				newob->damage = damage;
				newob->ani_type = ANI_EXPLODE;
				newob->center_on(this);
				leader->skip_exit += 3; // can't hit us for 3 rounds ..
				if (on_screen())
					screenp->soundp->play_sound(SOUND_EXPLODE);
				// Now make new objects to seek out foes ..
				// First, are our offspring powerful enough at 1/2 our power?
				generic = (damage)/2;
				if (owner->myguy)
					foelist = screenp->find_foes_in_range(screenp->oblist,
					                                      240+(owner->myguy->intelligence/2), &temp, this);
				else
					foelist = screenp->find_foes_in_range(screenp->oblist,
					                                      240+stats->level*5, &temp, this);
				if (temp && generic>20) // more foes to find ..
				{
					here = foelist;
					numfoes = random(owner->stats->level)+1;
					while (here && numfoes--)
					{
						if (here->ob != leader && here->ob->skip_exit<1) // don't hit current guy, etc.
						{
							newob = screenp->add_ob(ORDER_FX, FAMILY_CHAIN);
							if (!newob)
							{
								delete_list(foelist);
								return 0; // failsafe
							}
							newob->owner = owner;  // our caster
							newob->leader = here->ob; // guy to attack
							newob->stats->level = stats->level;
							newob->stats->set_bit_flags(BIT_MAGICAL, 1);
							newob->damage = generic;
							newob->team_num = team_num;
							newob->center_on(this);
						} // end of wasn't current guy case
						here = here->next;
					} // end of loop for nearby foes we found
				} // end of check for nearby foes

				// Clean up our list .. ?
				// Zardus: TAG: nah, lets use delete_list
				/*here = foelist->next;
				while (here)
				{
					delete foelist;
					foelist = here;
					here = here->next;
				}
				delete foelist;*/
				delete_list(foelist);
				dead = 1;
				death();
				return 1;
			}
			// Move toward our leader ..
			lineofsight--;
			distance = distance_to_ob_center(leader);
			if (distance > stepsize*2)
			{
				xd = yd = 0; // zero out distance movements
				if (leader->xpos > xpos)
				{
					if ( (leader->xpos - xpos) > stepsize )
						xd = stepsize;
					else
						xd = leader->xpos - xpos;
				}
				else if (leader->xpos < xpos)
				{
					if ( (xpos - leader->xpos) > stepsize )
						xd = -stepsize;
					else
						xd = leader->xpos - xpos;
				}
				if (leader->ypos > ypos)
				{
					if ( (leader->ypos - ypos) > stepsize )
						yd = stepsize;
					else
						yd = leader->ypos - ypos;
				}
				else if (leader->ypos < ypos)
				{
					if ( (ypos - leader->ypos) > stepsize )
						yd = -stepsize;
					else
						yd = leader->ypos - ypos;
				}
				// Set our facing?
				curdir = facing(xd, yd);
				set_frame(ani[curdir][0]);
			} // end of big step
			else
			{
				//xd = leader->xpos;
				//yd = leader->ypos;
				center_on(leader);
				return 1;
			}
			setxy((short) (xpos+xd), (short) (ypos+yd) );
			return 1;  // so as not to animate, etc.
			//break; // end of FAMILY_CHAIN

		case FAMILY_DOOR_OPEN:

			// Here is how doors work.  They start out as a FAMILY_DOOR
			//  from ORDER_WEAPON under the weaplist.  When the door is
			//  collided with, the obmap marks the door as dead, and spawns
			//  the FAMILY_DOOR_OPEN on the weaplist (this object).  It
			//  animates ANI_DOOR_OPEN, and when it is done, it dies and
			//  spawns a FAMILY_DOOR_OPEN on the fxlist.  The amusing part
			//  is that now that it is on the fxlist, it won't act anymore,
			//  thus preventing it from continuously respawning itself.

			if (ani_type != ANI_WALK)
				return animate();
			newob = screenp->add_fx_ob(ORDER_FX, FAMILY_DOOR_OPEN);
			if (!newob)
				break;
			newob->ani_type = ANI_WALK;
			newob->setxy(xpos, ypos);
			newob->stats->level = stats->level;
			newob->team_num = team_num;
			newob->ignore = 1;
			newob->curdir = curdir;
			// set correct frame
			newob->animate();
			dead = 1;
			death();
			return 1;
			break;

		default:
			break;
	}

	// Complete previous animations (like firing)
	if (ani_type != ANI_WALK)
		return animate();

	switch (family) // determine what to do..
	{
		default:
			dead = 1;
			death();
			break;
	}

	return 0;
}
示例#7
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;

}