Ejemplo n.º 1
0
void minotaurDie(Entity* my)
{
	int c;
	for ( c = 0; c < 5; c++ )
	{
		Entity* gib = spawnGib(my);
		serverSpawnGibForClient(gib);
	}

	my->spawnBlood();

	for ( c = 0; c < MAXPLAYERS; c++ )
	{
		playSoundPlayer(c, 114, 128);
	}

	my->removeMonsterDeathNodes();

	list_RemoveNode(my->mynode);
	return;
}
Ejemplo n.º 2
0
void actShopkeeperLimb(Entity *my) {
	int i;
	
	Entity *parent = NULL;
	if( (parent=uidToEntity(my->skill[2]))==NULL ) {
		list_RemoveNode(my->mynode);
		return;
	}
	
	if( multiplayer!=CLIENT ) {
		for( i=0; i<MAXPLAYERS; i++ ) {
			if( inrange[i] ) {
				if( i==0 && selectedEntity==my ) {
					parent->skill[13] = i+1;
				}
				else if( client_selected[i]==my ) {
					parent->skill[13] = i+1;
				}
			}
		}
	}
	return;
}
Ejemplo n.º 3
0
void actRightHandMagic(Entity *my)
{
	if (intro == TRUE) {
		my->flags[INVISIBLE] = TRUE;
		return;
	}

	//Initialize
	if( !HANDMAGIC_INIT ) {
		HANDMAGIC_INIT=1;
		my->focalz = -1.5;
	}

	if( players[clientnum]==NULL ) {
		magicRightHand=NULL;
		list_RemoveNode(my->mynode);
		return;
	}

	my->x = 8;
	my->y = 3;
	my->z = (camera.z *.5 - players[clientnum]->z) + 7;
	my->z -= 4;
	my->yaw = HANDMAGIC_YAW - camera_shakex2;
	double defaultpitch = (0-6.f) / PI;
	my->pitch = defaultpitch + HANDMAGIC_PITCH - camera_shakey2 / 200.f;
	my->roll = HANDMAGIC_ROLL;

	//Sprite
	bool noGloves=FALSE;
	if( stats[clientnum].gloves == NULL ) {
		noGloves=TRUE;
	} else {
		if( stats[clientnum].gloves->type == GLOVES || stats[clientnum].gloves->type == GLOVES_DEXTERITY ) {
			my->sprite = 132 + stats[clientnum].sex;
		} else if( stats[clientnum].gloves->type == BRACERS || stats[clientnum].gloves->type == BRACERS_CONSTITUTION ) {
			my->sprite = 323 + stats[clientnum].sex;
		} else if( stats[clientnum].gloves->type == GAUNTLETS || stats[clientnum].gloves->type == GAUNTLETS_STRENGTH ) {
			my->sprite = 140 + stats[clientnum].sex;
		} else {
			noGloves = TRUE;
		}
	}
	if( noGloves ) {
		if( stats[clientnum].appearance/6==0 ) {
			if( stats[clientnum].sex==FEMALE ) {
				my->sprite = 121;
			} else {
				my->sprite = 109;
			}
		} else if( stats[clientnum].appearance/6==1 ) {
			if( stats[clientnum].sex==FEMALE ) {
				my->sprite = 350;
			} else {
				my->sprite = 337;
			}
		} else {
			if( stats[clientnum].sex==FEMALE ) {
				my->sprite = 376;
			} else {
				my->sprite = 363;
			}
		}
	}

	bool wearingring = FALSE;

	//Select model
	if (stats[clientnum].ring != NULL)
		if (stats[clientnum].ring->type == RING_INVISIBILITY)
			wearingring = TRUE;
	if (stats[clientnum].cloak != NULL)
		if (stats[clientnum].cloak->type == CLOAK_INVISIBILITY)
			wearingring = TRUE;
	if (players[clientnum]->skill[3] == 1 || stats[clientnum].EFFECTS[EFF_INVISIBLE] == TRUE || wearingring ) { // debug cam or player invisible
		my->flags[INVISIBLE] = TRUE;
	}

	if (cast_animation.active) {
		switch (cast_animation.stage) {
			case CIRCLE:
				if (ticks%5==0) {
					//messagePlayer(0, "Pingas!");
					Entity *entity = spawnGib(my);
					entity->flags[INVISIBLE] = FALSE;
					entity->flags[SPRITE] = TRUE;
					entity->flags[NOUPDATE] = TRUE;
					entity->flags[UPDATENEEDED] = FALSE;
					entity->flags[OVERDRAW] = TRUE;
					entity->flags[BRIGHT] = TRUE;
					//entity->sizex = 1; //MAKE 'EM SMALL PLEASE!
					//entity->sizey = 1;
					entity->scalex = 0.25f; //MAKE 'EM SMALL PLEASE!
					entity->scaley = 0.25f;
					entity->scalez = 0.25f;
					entity->sprite = 16; //TODO: Originally. 22. 16 -- spark sprite instead?
					entity->yaw = ((rand()%6)*60)*PI/180.0;
					entity->pitch = (rand()%360)*PI/180.0;
					entity->roll = (rand()%360)*PI/180.0;
					entity->vel_x = cos(entity->yaw)*.1;
					entity->vel_y = sin(entity->yaw)*.1;
					entity->vel_z = -.15;
					entity->fskill[3] = 0.01;
				}
				break;
			case THROW:
				break;
			default:
				break;
		}
	}

	//Final position code.
	if( players[clientnum] == NULL )
		return;
	//double defaultpitch = PI / 8.f;
	//double defaultpitch = 0;
	//double defaultpitch = PI / (0-4.f);
	defaultpitch = (0-6.f) / PI;
	//my->x = 6 + HUDWEAPON_MOVEX;
	my->x = 8;
	my->x += cast_animation.lefthand_movex;
	//my->y = 3 + HUDWEAPON_MOVEY;
	my->y = 3;
	my->y -= cast_animation.lefthand_movey;
	//my->z = (camera.z*.5-players[clientnum]->z)+7+HUDWEAPON_MOVEZ;
	my->z = (camera.z *.5 - players[clientnum]->z) + 7;
	my->z -= 4;
	my->yaw = HANDMAGIC_YAW - camera_shakex2;
	my->pitch = defaultpitch + HANDMAGIC_PITCH - camera_shakey2 / 200.f;
	my->roll = HANDMAGIC_ROLL;
}
Ejemplo n.º 4
0
void actLeftHandMagic(Entity *my)
{
	//int c = 0;
	if (intro == TRUE) {
		my->flags[INVISIBLE] = TRUE;
		return;
	}

	//Initialize
	if (!HANDMAGIC_INIT) {
		HANDMAGIC_INIT = 1;
		HANDMAGIC_TESTVAR = 0;
		my->focalz = -1.5;
	}

	if( players[clientnum]==NULL ) {
		magicLeftHand = NULL;
		spellcastingAnimationManager_deactivate(&cast_animation);
		list_RemoveNode(my->mynode);
		return;
	}

	//Set the initial values. (For the particle spray)
	my->x = 8;
	my->y = -3;
	my->z = (camera.z *.5 - players[clientnum]->z) + 7;
	my->z -= 4;
	my->yaw = HANDMAGIC_YAW - camera_shakex2;
	double defaultpitch = (0-6.f) / PI;
	my->pitch = defaultpitch + HANDMAGIC_PITCH - camera_shakey2 / 200.f;
	my->roll = HANDMAGIC_ROLL;

	//Sprite
	bool noGloves=FALSE;
	if( stats[clientnum].gloves == NULL ) {
		noGloves=TRUE;
	} else {
		if( stats[clientnum].gloves->type == GLOVES || stats[clientnum].gloves->type == GLOVES_DEXTERITY ) {
			my->sprite = 136 + stats[clientnum].sex;
		} else if( stats[clientnum].gloves->type == BRACERS || stats[clientnum].gloves->type == BRACERS_CONSTITUTION ) {
			my->sprite = 327 + stats[clientnum].sex;
		} else if( stats[clientnum].gloves->type == GAUNTLETS || stats[clientnum].gloves->type == GAUNTLETS_STRENGTH ) {
			my->sprite = 144 + stats[clientnum].sex;
		} else {
			noGloves = TRUE;
		}
	}
	if( noGloves ) {
		if( stats[clientnum].appearance/6==0 ) {
			if( stats[clientnum].sex==FEMALE ) {
				my->sprite = 122;
			} else {
				my->sprite = 110;
			}
		} else if( stats[clientnum].appearance/6==1 ) {
			if( stats[clientnum].sex==FEMALE ) {
				my->sprite = 351;
			} else {
				my->sprite = 338;
			}
		} else {
			if( stats[clientnum].sex==FEMALE ) {
				my->sprite = 377;
			} else {
				my->sprite = 364;
			}
		}
	}

	bool wearingring = FALSE;

	//Select model
	if (stats[clientnum].ring != NULL)
		if (stats[clientnum].ring->type == RING_INVISIBILITY)
			wearingring = TRUE;
	if (stats[clientnum].cloak != NULL)
		if (stats[clientnum].cloak->type == CLOAK_INVISIBILITY)
			wearingring = TRUE;
	if (players[clientnum]->skill[3] == 1 || stats[clientnum].EFFECTS[EFF_INVISIBLE] == TRUE || wearingring ) { // debug cam or player invisible
		my->flags[INVISIBLE] = TRUE;
	}

	if (cast_animation.active) {
		switch (cast_animation.stage) {
			case CIRCLE:
				if(ticks%5==0) {
					Entity *entity = spawnGib(my);
					entity->flags[INVISIBLE] = FALSE;
					entity->flags[SPRITE] = TRUE;
					entity->flags[NOUPDATE] = TRUE;
					entity->flags[UPDATENEEDED] = FALSE;
					entity->flags[OVERDRAW] = TRUE;
					entity->flags[BRIGHT] = TRUE;
					entity->scalex = 0.25f; //MAKE 'EM SMALL PLEASE!
					entity->scaley = 0.25f;
					entity->scalez = 0.25f;
					entity->sprite = 16; //TODO: Originally. 22. 16 -- spark sprite instead?
					entity->yaw = ((rand()%6)*60)*PI/180.0;
					entity->pitch = (rand()%360)*PI/180.0;
					entity->roll = (rand()%360)*PI/180.0;
					entity->vel_x = cos(entity->yaw)*.1;
					entity->vel_y = sin(entity->yaw)*.1;
					entity->vel_z = -.15;
					entity->fskill[3] = 0.01;
				}
				cast_animation.consume_timer--;
				if (cast_animation.consume_timer < 0 && cast_animation.mana_left > 0) {
					//Time to consume mana and reset the ticker!
					cast_animation.consume_timer = cast_animation.consume_interval;
					if (multiplayer == SINGLE) {
						players[clientnum]->drainMP(1);
					}
					cast_animation.mana_left--;
				}

				cast_animation.lefthand_angle += HANDMAGIC_CIRCLE_SPEED;
				cast_animation.lefthand_movex = cos(cast_animation.lefthand_angle) * HANDMAGIC_CIRCLE_RADIUS;
				cast_animation.lefthand_movey = sin(cast_animation.lefthand_angle) * HANDMAGIC_CIRCLE_RADIUS;
				if (cast_animation.lefthand_angle >= 2 * PI) { //Completed one loop.
					cast_animation.lefthand_angle = 0;
					cast_animation.circle_count++;
					if (cast_animation.circle_count >= cast_animation.times_to_circle)
						//Finished circling. Time to move on!
						cast_animation.stage++;
				}
				break;
			case THROW:
				//messagePlayer(clientnum, "IN THROW");
				//TODO: Throw animation! Or something.
				cast_animation.stage++;
				break;
			default:
				//messagePlayer(clientnum, "DEFAULT CASE");
				spellcastingAnimationManager_completeSpell(&cast_animation);
				break;
		}
	}

	//Final position code.
	if( players[clientnum] == NULL )
		return;
	//double defaultpitch = PI / 8.f;
	//double defaultpitch = 0;
	//double defaultpitch = PI / (0-4.f);
	defaultpitch = (0-6.f) / PI;
	//my->x = 6 + HUDWEAPON_MOVEX;
	my->x += cast_animation.lefthand_movex;
	//my->y = 3 + HUDWEAPON_MOVEY;
	my->y = -3;
	my->y += cast_animation.lefthand_movey;
	//my->z = (camera.z*.5-players[clientnum]->z)+7+HUDWEAPON_MOVEZ;
	my->z = (camera.z *.5 - players[clientnum]->z) + 7;
	my->z -= 4;
	my->yaw = HANDMAGIC_YAW - camera_shakex2;
	my->pitch = defaultpitch + HANDMAGIC_PITCH - camera_shakey2 / 200.f;
	my->roll = HANDMAGIC_ROLL;
}
Ejemplo n.º 5
0
void actMinotaurCeilingBuster(Entity* my)
{
	double x, y;

	// levitate particles
	int u = std::min<unsigned int>(std::max<int>(0, my->x / 16), map.width - 1);
	int v = std::min<unsigned int>(std::max<int>(0, my->y / 16), map.height - 1);
	if ( !map.tiles[v * MAPLAYERS + u * MAPLAYERS * map.height] )
	{
		int c;
		for ( c = 0; c < 2; c++ )
		{
			Entity* entity = newEntity(171, 1, map.entities, nullptr); //Particle entity.
			entity->x = my->x - 8 + rand() % 17;
			entity->y = my->y - 8 + rand() % 17;
			entity->z = 10 + rand() % 3;
			entity->scalex = 0.7;
			entity->scaley = 0.7;
			entity->scalez = 0.7;
			entity->sizex = 1;
			entity->sizey = 1;
			entity->yaw = (rand() % 360) * PI / 180.f;
			entity->flags[PASSABLE] = true;
			entity->flags[BRIGHT] = true;
			entity->flags[NOUPDATE] = true;
			entity->flags[UNCLICKABLE] = true;
			entity->behavior = &actMagicParticle;
			if ( multiplayer != CLIENT )
			{
				entity_uids--;
			}
			entity->setUID(-3);
		}
	}

	// bust ceilings
	for ( x = my->x - my->sizex - 1; x <= my->x + my->sizex + 1; x += 1 )
	{
		for ( y = my->y - my->sizey - 1; y <= my->y + my->sizey + 1; y += 1 )
		{
			if ( x >= 0 && y >= 0 && x < map.width << 4 && y < map.height << 4 )
			{
				int index = (MAPLAYERS - 1) + ((int)floor(y / 16)) * MAPLAYERS + ((int)floor(x / 16)) * MAPLAYERS * map.height;
				if ( map.tiles[index] )
				{
					if ( my->monsterAttack == 0 )
					{
						if ( multiplayer != CLIENT )
						{
							my->attack(MONSTER_POSE_MELEE_WINDUP2, 0, nullptr);
						}
						return;
					}
					else if ( my->monsterAttack == MONSTER_POSE_MELEE_WINDUP2 )
					{
						return;
					}
					map.tiles[index] = 0;
					if ( multiplayer != CLIENT )
					{
						playSoundEntity(my, 67, 128);
						//MONSTER_ATTACK = 1;
						Stat* myStats = my->getStats();
						if ( myStats )
						{
							// easy hack to stop the minotaur while he breaks stuff
							myStats->EFFECTS[EFF_PARALYZED] = true;
							myStats->EFFECTS_TIMERS[EFF_PARALYZED] = 10;
						}
					}

					// spawn several rock particles (NOT items)
					int c, i = 6 + rand() % 4;
					for ( c = 0; c < i; c++ )
					{
						Entity *entity = nullptr;
						if ( multiplayer == SERVER )
						{
							entity = spawnGib(my);
						}
						else
						{
							entity = spawnGibClient(my->x, my->y, my->z, 5);
						}
						if ( entity )
						{
							entity->x = ((int)(my->x / 16)) * 16 + rand() % 16;
							entity->y = ((int)(my->y / 16)) * 16 + rand() % 16;
							entity->z = -8;
							entity->flags[PASSABLE] = true;
							entity->flags[INVISIBLE] = false;
							entity->flags[NOUPDATE] = true;
							entity->flags[UPDATENEEDED] = false;
							entity->sprite = items[GEM_ROCK].index;
							entity->yaw = rand() % 360 * PI / 180;
							entity->pitch = rand() % 360 * PI / 180;
							entity->roll = rand() % 360 * PI / 180;
							entity->vel_x = (rand() % 20 - 10) / 10.0;
							entity->vel_y = (rand() % 20 - 10) / 10.0;
							entity->vel_z = -.25;
							entity->fskill[3] = 0.03;
						}
					}
				}
				node_t* node, *nextnode;
				std::vector<list_t*> entLists = TileEntityList.getEntitiesWithinRadiusAroundEntity(my, 2);
				for ( std::vector<list_t*>::iterator it = entLists.begin(); it != entLists.end(); ++it )
				{
					list_t* currentList = *it;
					for ( node = currentList->first; node != nullptr; node = nextnode )
					{
						nextnode = node->next;
						Entity* entity = (Entity*)node->element;
						if ( (int)(x / 16) == (int)(entity->x / 16) && (int)(y / 16) == (int)(entity->y / 16) )
						{
							if ( entity->behavior == &actDoorFrame )
							{
								// spawn several rock items
								int c, i = 8 + rand() % 4;
								for ( c = 0; c < i; c++ )
								{
									Entity *entity = nullptr;
									if ( multiplayer == SERVER )
									{
										entity = spawnGib(my);
									}
									else
									{
										entity = spawnGibClient(my->x, my->y, my->z, 5);
									}
									if ( entity )
									{
										entity->x = ((int)(my->x / 16)) * 16 + rand() % 16;
										entity->y = ((int)(my->y / 16)) * 16 + rand() % 16;
										entity->z = -8;
										entity->flags[PASSABLE] = true;
										entity->flags[INVISIBLE] = false;
										entity->flags[NOUPDATE] = true;
										entity->flags[UPDATENEEDED] = false;
										entity->sprite = items[GEM_ROCK].index;
										entity->yaw = rand() % 360 * PI / 180;
										entity->pitch = rand() % 360 * PI / 180;
										entity->roll = rand() % 360 * PI / 180;
										entity->vel_x = (rand() % 20 - 10) / 10.0;
										entity->vel_y = (rand() % 20 - 10) / 10.0;
										entity->vel_z = -.25;
										entity->fskill[3] = 0.03;
									}
								}
								list_RemoveNode(entity->mynode);
							}
							else if ( entity->behavior == &actDoor )
							{
								if ( multiplayer != CLIENT )
								{
									entity->skill[4] = 0; // destroy the door
								}
							}
							else if ( entity->behavior == &actGate )
							{
								if ( multiplayer != CLIENT )
								{
									playSoundEntity(entity, 76, 64);
									list_RemoveNode(entity->mynode);
								}
							}
							else if (	entity->behavior == &actStalagCeiling	||
										entity->behavior == &actStalagFloor		||
										entity->behavior == &actStalagColumn
									)
							{
								// spawn several rock items
								int c, i = rand() % 4;
								for ( c = 0; c < i; ++c )
								{
									//Entity* childEntity = spawnGib(my);
									Entity *childEntity = nullptr;
									if ( multiplayer == SERVER )
									{
										childEntity = spawnGib(my);
									}
									else
									{
										childEntity = spawnGibClient(my->x, my->y, my->z, 5);
									}
									if ( entity )
									{
										childEntity->x = ((int)(my->x / 16)) * 16 + rand() % 16;
										childEntity->y = ((int)(my->y / 16)) * 16 + rand() % 16;
										childEntity->z = -8;
										childEntity->flags[PASSABLE] = true;
										childEntity->flags[INVISIBLE] = false;
										childEntity->flags[NOUPDATE] = true;
										childEntity->flags[UPDATENEEDED] = false;
										childEntity->sprite = items[GEM_ROCK].index;
										childEntity->yaw = rand() % 360 * PI / 180;
										childEntity->pitch = rand() % 360 * PI / 180;
										childEntity->roll = rand() % 360 * PI / 180;
										childEntity->vel_x = (rand() % 20 - 10) / 10.0;
										childEntity->vel_y = (rand() % 20 - 10) / 10.0;
										childEntity->vel_z = -.25;
										childEntity->fskill[3] = 0.03;
									}
								}
								list_RemoveNode(entity->mynode);
							}
						}
					}
				}
			}
		}
	}
}
Ejemplo n.º 6
0
void actMinotaurTimer(Entity* my)
{
	node_t* node;

	MINOTAURTIMER_LIFE++;
	if (( (currentlevel < 25 && MINOTAURTIMER_LIFE == TICKS_PER_SECOND * 120)
			|| (currentlevel >= 25 && MINOTAURTIMER_LIFE == TICKS_PER_SECOND * 180)
		)
		&& rand() % 5 == 0 )   // two minutes if currentlevel < 25, else 3 minutes.
	{
		int c;
		bool spawnedsomebody = false;
		for ( c = 0; c < 9; c++ )
		{
			Uint32 zapLeaderUid = 0;
			Entity* monster = summonMonster(HUMAN, my->x, my->y);
			if ( monster )
			{
				monster->skill[29] = 1; // so we spawn a zap brigadier
				spawnedsomebody = true;
				if ( !zapLeaderUid )
				{
					zapLeaderUid = monster->getUID();
				}
				else
				{
					Stat* monsterStats = monster->getStats();
					monsterStats->leader_uid = zapLeaderUid;
				}
			}
		}

		if ( spawnedsomebody )
		{
#ifdef MUSIC
			fadein_increment = default_fadein_increment * 20;
			fadeout_increment = default_fadeout_increment * 5;
			playmusic( sounds[175], false, true, false);
#endif
			for ( c = 0; c < MAXPLAYERS; c++ )
			{
				Uint32 color = SDL_MapRGB(mainsurface->format, 0, 255, 255);
				if ( stats[c]->type == HUMAN )
				{
					messagePlayerColor(c, color, language[1114], stats[c]->name);
				}
				else
				{
					messagePlayerColor(c, color, language[3285]);
				}
			}
		}
	}
	else if (( (currentlevel < 25 && MINOTAURTIMER_LIFE >= TICKS_PER_SECOND * 150)
					|| (currentlevel >= 25 && MINOTAURTIMER_LIFE >= TICKS_PER_SECOND * 210)
				)
		&& !MINOTAURTIMER_ACTIVE )     // two and a half minutes if currentlevel < 25, else 3.5 minutes
	{
		Entity* monster = summonMonster(MINOTAUR, my->x, my->y);
		if ( monster )
		{
			int c;
			for ( c = 0; c < MAXPLAYERS; c++ )
			{
				playSoundPlayer( c, 107 + rand() % 3, 128 );
				Uint32 color = SDL_MapRGB(mainsurface->format, 255, 128, 0);
				messagePlayerColor(c, color, language[1115]);
			}
			MINOTAURTIMER_ACTIVE = MINOTAURTIMER_LIFE;
		}
	}
	if ( MINOTAURTIMER_ACTIVE && MINOTAURTIMER_LIFE >= MINOTAURTIMER_ACTIVE + TICKS_PER_SECOND * 3 )
	{
		int c;
		for ( c = 0; c < MAXPLAYERS; c++ )
		{
			if ( currentlevel < 25 )
			{
				playSoundPlayer(c, 120 + rand() % 3, 128);
				Uint32 color = SDL_MapRGB(mainsurface->format, 255, 0, 255);
				messagePlayerColor(c, color, language[1116]);
				messagePlayerColor(c, color, language[73]);
			}
			else
			{
				playSoundPlayer(c, 375, 128);
				playSoundPlayer(c, 379, 128);
				messagePlayerColor(c, uint32ColorOrange(*mainsurface), language[1116]);
				messagePlayerColor(c, uint32ColorOrange(*mainsurface), language[73]);
				messagePlayerColor(c, uint32ColorBaronyBlue(*mainsurface), language[73]);
			}
		}
		list_RemoveNode(my->mynode);
		return;
	}
}
Ejemplo n.º 7
0
int boulderCheckAgainstEntity(Entity *my, Entity *entity) {
	if (!my || !entity)
		return 0;

	if( entity->behavior == &actPlayer || entity->behavior == &actMonster ) {
		if( entityInsideEntity( my, entity ) ) {
			Stat *stats = entity->getStats();
			if( stats ) {
				if( entity->behavior==&actPlayer ) {
					Uint32 color = SDL_MapRGB(mainsurface->format,255,0,0);
					messagePlayerColor(entity->skill[2],color,language[455]);
					if( entity->skill[2] == clientnum ) {
						camera_shakex += .1;
						camera_shakey += 10;
					} else {
						strcpy((char *)net_packet->data,"SHAK");
						net_packet->data[4]=10; // turns into .1
						net_packet->data[5]=10;
						net_packet->address.host = net_clients[entity->skill[2]-1].host;
						net_packet->address.port = net_clients[entity->skill[2]-1].port;
						net_packet->len = 6;
						sendPacketSafe(net_sock, -1, net_packet, entity->skill[2]-1);
					}
				}
				playSoundEntity(my,181,128);
				playSoundEntity(entity,28,64);
				spawnGib(entity);
				entity->modHP(-80);
				entity->setObituary(language[1505]);
				if( entity->behavior==&actPlayer )
					if( stats->HP<=0 )
						steamAchievementClient(entity->skill[2],"BARONY_ACH_THROW_ME_THE_WHIP");
				if( stats->HP > 0 ) {
					// spawn several rock items
					int i = 8+rand()%4;
					
					int c;
					for( c=0; c<i; c++ ) {
						Entity *entity = newEntity(-1,1,map.entities);
						entity->flags[INVISIBLE]=TRUE;
						entity->flags[UPDATENEEDED]=TRUE;
						entity->x = my->x - 4 + rand()%8;
						entity->y = my->y - 4 + rand()%8;
						entity->z = -6+rand()%12;
						entity->sizex = 4;
						entity->sizey = 4;
						entity->yaw = rand()%360 * PI/180;
						entity->vel_x = (rand()%20-10)/10.0;
						entity->vel_y = (rand()%20-10)/10.0;
						entity->vel_z = -.25 - (rand()%5)/10.0;
						entity->flags[PASSABLE] = TRUE;
						entity->behavior = &actItem;
						entity->flags[USERFLAG1] = TRUE; // no collision: helps performance
						entity->skill[10] = GEM_ROCK;    // type
						entity->skill[11] = WORN;        // status
						entity->skill[12] = 0;           // beatitude
						entity->skill[13] = 1;           // count
						entity->skill[14] = 0;           // appearance
						entity->skill[15] = FALSE;       // identified
					}

					double ox = my->x;
					double oy = my->y;
					
					// destroy the boulder
					playSoundEntity(my,67,128);
					list_RemoveNode(my->mynode);

					// on sokoban, destroying boulders spawns scorpions
					if( !strcmp(map.name,"Sokoban") ) {
						Entity *monster = summonMonster(SCORPION,ox,oy);
						if( monster ) {
							int c;
							for( c=0; c<MAXPLAYERS; c++ ) {
								Uint32 color = SDL_MapRGB(mainsurface->format,255,128,0);
								messagePlayerColor(c,color,language[406]);
							}
						}
					}

					return 1;
				}
			}
		}
	} else if( entity->behavior == &actGate || entity->behavior == &actBoulder || entity->behavior==&actChest || entity->behavior==&actHeadstone || entity->behavior==&actFountain || entity->behavior==&actSink ) {
		if( !entity->flags[PASSABLE] ) {
			if( entityInsideEntity( my, entity ) ) {
				// stop the boulder
				BOULDER_STOPPED=1;
				BOULDER_ROLLING=0;
				playSoundEntity(my,181,128);
				if( my->flags[PASSABLE] ) {
					my->flags[PASSABLE] = FALSE;
					if( multiplayer==SERVER )
						serverUpdateEntityFlag(my,PASSABLE);
				}
			}
		}
	} else if( entity->behavior == &actDoor ) {
		if( entityInsideEntity( my, entity ) ) {
			playSoundEntity(entity,28,64);
			entity->skill[4] = 0;
			if( !entity->skill[0] )
				entity->skill[6] = (my->x > entity->x);
			else
				entity->skill[6] = (my->y < entity->y);
			playSoundEntity(my,181,128);
		}
	}
	return 0;
}
Ejemplo n.º 8
0
void actBoulder(Entity *my) {
	int i;
	
	my->skill[2]=-7; // invokes actEmpty() on clients
	my->flags[UPDATENEEDED] = TRUE;

	bool noground=FALSE;
	int x = std::min<int>(std::max(0,(int)(my->x/16)),map.width);
	int y = std::min<int>(std::max(0,(int)(my->y/16)),map.height);
	Uint32 index = y*MAPLAYERS+x*MAPLAYERS*map.height;
	if( !map.tiles[index] || animatedtiles[map.tiles[index]] )
		noground = TRUE;

	// gravity
	bool nobounce=TRUE;
	if( !BOULDER_NOGROUND )
		if( noground )
			BOULDER_NOGROUND = TRUE;
	if( my->z < 0 || BOULDER_NOGROUND ) {
		my->vel_z = std::min(my->vel_z+.1,3.0);
		nobounce = TRUE;
		if( my->z >= 128 ) {
			list_RemoveNode(my->mynode);
			return;
		}
		if( !BOULDER_NOGROUND ) {
			if( my->z >= -8 && fabs(my->vel_z) > 2 ) {
				node_t *node;
				for( node=map.entities->first; node!=NULL; node=node->next ) {
					Entity *entity = (Entity *)node->element;
					if( entity == my )
						continue;
					if( boulderCheckAgainstEntity(my,entity) )
						return;
				}
			}
		}
	} else {
		if( fabs(my->vel_z) > 1 ) {
			playSoundEntity(my,182,128);
			my->vel_z = -(my->vel_z/2);
			nobounce = TRUE;
		} else {
			if( my->vel_z )
				playSoundEntity(my,182,128);
			my->vel_z = 0;
			nobounce = FALSE;
		}
		my->z = 0;
	}
	my->z += my->vel_z;
	if( nobounce ) {
		if( !my->flags[PASSABLE] ) {
			my->flags[PASSABLE] = TRUE;
			if( multiplayer==SERVER )
				serverUpdateEntityFlag(my,PASSABLE);
		}
		if( !BOULDER_STOPPED ) {
			my->x += my->vel_x;
			my->y += my->vel_y;
			double dist = sqrt(pow(my->vel_x,2)+pow(my->vel_y,2));
			my->pitch += dist*.06;
			my->roll = PI/2;
		}
	} else if( !BOULDER_STOPPED ) {
		if( my->flags[PASSABLE] ) {
			my->flags[PASSABLE] = FALSE;
			if( multiplayer==SERVER )
				serverUpdateEntityFlag(my,PASSABLE);
		}
		
		// horizontal velocity
		my->vel_x += cos(my->yaw)*.1;
		my->vel_y += sin(my->yaw)*.1;
		if( my->vel_x > 1.5 )
			my->vel_x = 1.5;
		if( my->vel_x < -1.5 )
			my->vel_x = -1.5;
		if( my->vel_y > 1.5 )
			my->vel_y = 1.5;
		if( my->vel_y < -1.5 )
			my->vel_y = -1.5;
		int x = std::min<int>(std::max(0.0,(my->x+cos(my->yaw)*8)/16),map.width-1);
		int y = std::min<int>(std::max(0.0,(my->y+sin(my->yaw)*8)/16),map.height-1);
		if( map.tiles[OBSTACLELAYER+y*MAPLAYERS+x*MAPLAYERS*map.height] ) {
			playSoundEntity(my,181,128);
			BOULDER_STOPPED = 1;
		} else {
			my->x += my->vel_x;
			my->y += my->vel_y;
			double dist = sqrt(pow(my->vel_x,2)+pow(my->vel_y,2));
			my->pitch += dist*.06;
			my->roll = PI/2;
		
			// crush objects
			if( dist && !BOULDER_NOGROUND ) {
				node_t *node;
				for( node=map.entities->first; node!=NULL; node=node->next ) {
					Entity *entity = (Entity *)node->element;
					if( entity == my )
						continue;
					if( boulderCheckAgainstEntity(my,entity) )
						return;
				}
			}
		}
	}
	
	// pushing boulders
	if( BOULDER_STOPPED ) {
		if( !BOULDER_ROLLING ) {
			for(i=0;i<MAXPLAYERS;i++) {
				if( (i==0 && selectedEntity==my) || (client_selected[i]==my) ) {
					if(inrange[i]) {
						if( statGetSTR(stats[i])<5 ) {
							messagePlayer(i,language[456]);
						} else {
							if( players[i] ) {
								playSoundEntity(my, 151, 128);
								BOULDER_ROLLING=1;
								my->x = floor(my->x/16)*16+8;
								my->y = floor(my->y/16)*16+8;
								BOULDER_DESTX=(int)(my->x/16)*16+8;
								BOULDER_DESTY=(int)(my->y/16)*16+8;
								if( (int)(players[i]->x/16) < (int)(my->x/16) ) {
									BOULDER_ROLLDIR=0; // east
								} else if( (int)(players[i]->y/16) < (int)(my->y/16) ) {
									BOULDER_ROLLDIR=1; // south
								} else if( (int)(players[i]->x/16) > (int)(my->x/16) ) {
									BOULDER_ROLLDIR=2; // west
								} else if( (int)(players[i]->y/16) > (int)(my->y/16) ) {
									BOULDER_ROLLDIR=3; // north
								}
								switch( BOULDER_ROLLDIR ) {
									case 0:
										BOULDER_DESTX += 16;
										break;
									case 1:
										BOULDER_DESTY += 16;
										break;
									case 2:
										BOULDER_DESTX -= 16;
										break;
									case 3:
										BOULDER_DESTY -= 16;
										break;
								}
							}
						}
					}
				}
			}
		} else {
			switch( BOULDER_ROLLDIR ) {
				case 0:
					my->vel_x=1;
					my->vel_y=0;
					break;
				case 1:
					my->vel_x=0;
					my->vel_y=1;
					break;
				case 2:
					my->vel_x=-1;
					my->vel_y=0;
					break;
				case 3:
					my->vel_x=0;
					my->vel_y=-1;
					break;
			}
			int x = (my->x+my->vel_x*8)/16;
			int y = (my->y+my->vel_y*8)/16;
			x = std::min<unsigned int>(std::max(0,x),map.width-1);
			y = std::min<unsigned int>(std::max(0,y),map.height-1);
			if( map.tiles[OBSTACLELAYER+y*MAPLAYERS+x*MAPLAYERS*map.height] ) {
				BOULDER_ROLLING = 0;
			} else {
				my->x += my->vel_x;
				my->y += my->vel_y;
				double dist = sqrt(pow(my->vel_x,2)+pow(my->vel_y,2));
				my->pitch += dist*.06;

				if( BOULDER_ROLLDIR==0 ) {
					if( my->x>=BOULDER_DESTX ) {
						my->x=BOULDER_DESTX;
						BOULDER_ROLLING=0;
					}
				} else if( BOULDER_ROLLDIR==1 ) {
					if( my->y>=BOULDER_DESTY ) {
						my->y=BOULDER_DESTY;
						BOULDER_ROLLING=0;
					}
				} else if( BOULDER_ROLLDIR==2 ) {
					if( my->x<=BOULDER_DESTX ) {
						my->x=BOULDER_DESTX;
						BOULDER_ROLLING=0;
					}
				} else if( BOULDER_ROLLDIR==3 ) {
					if( my->y<=BOULDER_DESTY ) {
						my->y=BOULDER_DESTY;
						BOULDER_ROLLING=0;
					}
				}
				double dir = my->yaw - BOULDER_ROLLDIR*PI/2;
				while( dir >= PI )
					dir -= PI*2;
				while( dir < -PI )
					dir += PI*2;
				my->yaw -= dir/16;
				while( my->yaw < 0 )
					my->yaw += 2*PI;
				while( my->yaw >= 2*PI )
					my->yaw -= 2*PI;
		
				// crush objects
				if( dist && !BOULDER_NOGROUND ) {
					node_t *node;
					for( node=map.entities->first; node!=NULL; node=node->next ) {
						Entity *entity = (Entity *)node->element;
						if( entity == my )
							continue;
						if( boulderCheckAgainstEntity(my,entity) )
							return;
					}
				}
			}
		}
	}

	// wrap around angles
	while( my->pitch >= PI*2 )
		my->pitch -= PI*2;
	while( my->pitch < 0 )
		my->pitch += PI*2;
	while( my->roll >= PI*2 )
		my->roll -= PI*2;
	while( my->roll < 0 )
		my->roll += PI*2;
	
	// rolling sound
	if( !BOULDER_STOPPED && (fabs(my->vel_x)>0 || fabs(my->vel_y)>0) ) {
		BOULDER_AMBIENCE++;
		if( BOULDER_AMBIENCE>=TICKS_PER_SECOND/3 ) {
			BOULDER_AMBIENCE=0;
			playSoundEntity(my, 151, 128);
		}
	}
}
Ejemplo n.º 9
0
void castSpellInit(Uint32 caster_uid, spell_t *spell){
	Entity *caster = uidToEntity(caster_uid);
	node_t *node = NULL;
	if (!caster || !spell)
	{
		//Need a spell and caster to cast a spell.
		return;
	}

	if (!spell->elements.first) {
		return;
	}

	if (hudweapon) {
		if (hudweapon->skill[0] != 0) { //HUDWEAPON_CHOP.
			return; //Can't cast spells while attacking.
		}
	}

	if (cast_animation.active) {
		//Already casting spell.
		return;
	}

	int player = -1;
	int i = 0;
	for (i = 0; i < numplayers; ++i) {
		if (caster == players[i]) {
			player = i; //Set the player.
		}
	}

	if (player > -1) {
		if( stats[player].defending ) {
			messagePlayer(player,language[407]);
			return;
		}
		if (spell_isChanneled(spell)) {
			if (channeledSpells[clientnum], spell) {
				for (node = channeledSpells[player].first; node; node = node->next) {
					spell_t *spell_search = (spell_t*)node->element;
					if (spell_search->ID == spell->ID) {
						//list_RemoveNode(node);
						//node = NULL;
						spell_search->sustain = FALSE;
						//if (spell->magic_effects)
						//	list_RemoveNode(spell->magic_effects);
						messagePlayer(player, language[408], spell->name);
						if (multiplayer == CLIENT) {
							list_RemoveNode(node);
							strcpy( (char *)net_packet->data, "UNCH");
							net_packet->data[4] = clientnum;
							SDLNet_Write32(spell->ID, &net_packet->data[5]);
							net_packet->address.host = net_server.host;
							net_packet->address.port = net_server.port;
							net_packet->len = 9;
							sendPacketSafe(net_sock, -1, net_packet, 0);
						}
						return;
					}
				}
			}
		}
	}

	int magiccost = 0;
	//Entity *entity = NULL;
	//node_t *node = spell->elements->first;

	stat_t *stat = caster->getStats();
	if( !stat )
		return;
	
	if (stat->EFFECTS[EFF_PARALYZED]) {
		return;		
	}

	magiccost = getCostOfSpell(spell);
	if (magiccost > stat->MP) {
		if (player >= 0)
			messagePlayer(player, language[375]); //TODO: Allow overexpending at the cost of extreme danger? (maybe an immensely powerful tree of magic actually likes this -- using your life-force to power spells instead of mana)
		return;
	}
	if (magiccost < 0) {
		if (player >= 0)
			messagePlayer(player, "Error: Invalid spell. Mana cost is negative?");
		return;
	}

	//Hand the torch off to the spell animator. And stuff. Stuff. I mean spell animation handler thingymabobber.
	fireOffSpellAnimation(&cast_animation, caster->uid, spell);

	//castSpell(caster, spell); //For now, do this while the spell animations are worked on.
}
Ejemplo n.º 10
0
void statDeconstructor(void *data) {
	stat_t *stat;
	if(data != NULL) {
		stat = (stat_t *)data;
		if( stat->helmet != NULL ) {
			if( stat->helmet->node == NULL )
				free(stat->helmet);
			else
				list_RemoveNode(stat->helmet->node);
			stat->helmet = NULL;
		}
		if( stat->breastplate != NULL ) {
			if( stat->breastplate->node == NULL )
				free(stat->breastplate);
			else
				list_RemoveNode(stat->breastplate->node);
			stat->breastplate = NULL;
		}
		if( stat->gloves != NULL ) {
			if( stat->gloves->node == NULL )
				free(stat->gloves);
			else
				list_RemoveNode(stat->gloves->node);
			stat->gloves = NULL;
		}
		if( stat->shoes != NULL ) {
			if( stat->shoes->node == NULL )
				free(stat->shoes);
			else
				list_RemoveNode(stat->shoes->node);
			stat->shoes = NULL;
		}
		if( stat->shield != NULL ) {
			if( stat->shield->node == NULL )
				free(stat->shield);
			else
				list_RemoveNode(stat->shield->node);
			stat->shield = NULL;
		}
		if( stat->weapon != NULL ) {
			if( stat->weapon->node == NULL )
				free(stat->weapon);
			else
				list_RemoveNode(stat->weapon->node);
			stat->weapon = NULL;
		}
		if( stat->cloak != NULL ) {
			if( stat->cloak->node == NULL )
				free(stat->cloak);
			else
				list_RemoveNode(stat->cloak->node);
			stat->cloak = NULL;
		}
		if( stat->amulet != NULL ) {
			if( stat->amulet->node == NULL )
				free(stat->amulet);
			else
				list_RemoveNode(stat->amulet->node);
			stat->amulet = NULL;
		}
		if( stat->ring != NULL ) {
			if( stat->ring->node == NULL )
				free(stat->ring);
			else
				list_RemoveNode(stat->ring->node);
			stat->ring = NULL;
		}
		if( stat->mask != NULL ) {
			if( stat->mask->node == NULL )
				free(stat->mask);
			else
				list_RemoveNode(stat->mask->node);
			stat->mask = NULL;
		}
		//Free memory for magic effects.
		node_t *spellnode;
		spellnode = stat->magic_effects.first;
		while (spellnode) {
			node_t *oldnode = spellnode;
			spellnode = spellnode->next;
			spell_t *spell = (spell_t*)oldnode->element;
			spell->magic_effects_node = NULL;
		}
		list_FreeAll(&stat->magic_effects);
		list_FreeAll(&stat->inventory);
		free(data);
	}
}
Ejemplo n.º 11
0
void freePlayerEquipment(int x) {
	if( stats[x].helmet != NULL ) {
		if( stats[x].helmet->node )
			list_RemoveNode(stats[x].helmet->node);
		else
			free(stats[x].helmet);
		stats[x].helmet = NULL;
	}
	if( stats[x].breastplate != NULL ) {
		if( stats[x].breastplate->node )
			list_RemoveNode(stats[x].breastplate->node);
		else
			free(stats[x].breastplate);
		stats[x].breastplate = NULL;
	}
	if( stats[x].gloves != NULL ) {
		if( stats[x].gloves->node )
			list_RemoveNode(stats[x].gloves->node);
		else
			free(stats[x].gloves);
		stats[x].gloves = NULL;
	}
	if( stats[x].shoes != NULL ) {
		if( stats[x].shoes->node )
			list_RemoveNode(stats[x].shoes->node);
		else
			free(stats[x].shoes);
		stats[x].shoes = NULL;
	}
	if( stats[x].shield != NULL ) {
		if( stats[x].shield->node )
			list_RemoveNode(stats[x].shield->node);
		else
			free(stats[x].shield);
		stats[x].shield = NULL;
	}
	if( stats[x].weapon != NULL ) {
		if( stats[x].weapon->node )
			list_RemoveNode(stats[x].weapon->node);
		else
			free(stats[x].weapon);
		stats[x].weapon = NULL;
	}
	if( stats[x].cloak != NULL ) {
		if( stats[x].cloak->node )
			list_RemoveNode(stats[x].cloak->node);
		else
			free(stats[x].cloak);
		stats[x].cloak = NULL;
	}
	if( stats[x].amulet != NULL ) {
		if( stats[x].amulet->node )
			list_RemoveNode(stats[x].amulet->node);
		else
			free(stats[x].amulet);
		stats[x].amulet = NULL;
	}
	if( stats[x].ring != NULL ) {
		if( stats[x].ring->node )
			list_RemoveNode(stats[x].ring->node);
		else
			free(stats[x].ring);
		stats[x].ring = NULL;
	}
	if( stats[x].mask != NULL ) {
		if( stats[x].mask->node )
			list_RemoveNode(stats[x].mask->node);
		else
			free(stats[x].mask);
		stats[x].mask = NULL;
	}
}
Ejemplo n.º 12
0
void actCampfire(Entity *my) {
	Entity *entity;
	int i;
	
	// init
	if( !CAMPFIRE_INIT ) {
		CAMPFIRE_INIT = 1;
		CAMPFIRE_HEALTH = MAXPLAYERS;
	}
		
	// crackling sounds
	if( CAMPFIRE_HEALTH>0 ) {
		CAMPFIRE_SOUNDTIME--;
		if( CAMPFIRE_SOUNDTIME <= 0 ) {
			CAMPFIRE_SOUNDTIME = 480;
			playSoundEntityLocal( my, 133, 128 );
		}
	
		// spew flame particles
		for( i=0; i<3; i++ ) {
			entity = spawnFlame(my);
			entity->x += ((rand()%30)-10)/10.f;
			entity->y += ((rand()%30)-10)/10.f;
			entity->z -= 1;
		}
		entity = spawnFlame(my);
		entity->z -= 2;
	
		// light environment
		if( !CAMPFIRE_LIGHTING ) {
			my->light = lightSphereShadow(my->x/16, my->y/16, 6, 160);
			CAMPFIRE_LIGHTING=1;
		}
		CAMPFIRE_FLICKER--;
		if(CAMPFIRE_FLICKER<=0) {
			CAMPFIRE_LIGHTING=(CAMPFIRE_LIGHTING==1)+1;
		
			if(CAMPFIRE_LIGHTING==1) {
				if( my->light != NULL )
					list_RemoveNode(my->light->node);
				my->light = lightSphereShadow(my->x/16, my->y/16, 6, 160);
			}
			else {
				if( my->light != NULL )
					list_RemoveNode(my->light->node);
				my->light = lightSphereShadow(my->x/16, my->y/16, 6, 152);
			}
			CAMPFIRE_FLICKER=2+rand()%7;
		}
	} else {
		if( my->light )
			if( my->light->node )
				list_RemoveNode(my->light->node);
		my->light = NULL;
		my->flags[BRIGHT] = FALSE;
	}

	if( multiplayer != CLIENT ) {
		// using campfire
		for(i=0;i<MAXPLAYERS;i++) {
			if( (i==0 && selectedEntity==my) || (client_selected[i]==my) ) {
				if(inrange[i]) {
					if( CAMPFIRE_HEALTH>0 ) {
						messagePlayer(i,language[457]);
						CAMPFIRE_HEALTH--;
						if( CAMPFIRE_HEALTH<=0 ) {
							serverUpdateEntitySkill(my,3); // extinguish for all clients
							messagePlayer(i,language[458]);
							if( my->light )
								if( my->light->node )
									list_RemoveNode(my->light->node);
							my->light = NULL;
						}
						Item *item = newItem(TOOL_TORCH,WORN,0,1,0,TRUE,NULL);
						itemPickup(i,item);
						free(item);
					} else {
						messagePlayer(i,language[458]);
					}
				}
			}
		}
	}
}
Ejemplo n.º 13
0
void actGoldBag(Entity *my) {
	int i;

	if( my->flags[INVISIBLE] ) {
		if( multiplayer!=CLIENT ) {
			node_t *node;
			for( node=map.entities->first; node!=NULL; node=node->next ) {
				Entity *entity = (Entity *)node->element;
				if( entity->sprite == 245 ) // boulder.vox
					return;
			}
			my->flags[INVISIBLE] = FALSE;
			serverUpdateEntityFlag(my,INVISIBLE);
			if( !strcmp(map.name,"Sokoban") ) {
				for( i=0; i<MAXPLAYERS; i++ )
					steamAchievementClient(i,"BARONY_ACH_PUZZLE_MASTER");
			}
		} else {
			return;
		}
	}

	GOLDBAG_AMBIENCE--;
	if( GOLDBAG_AMBIENCE<=0 ) {
		GOLDBAG_AMBIENCE = TICKS_PER_SECOND*30;
		playSoundEntityLocal( my, 149, 16 );
	}
	
	// pick up gold
	if( multiplayer!=CLIENT ) {
		for(i=0;i<MAXPLAYERS;i++) {
			if( (i==0 && selectedEntity==my) || (client_selected[i]==my) ) {
				if(inrange[i]) {
					if (players[i] && players[i]->entity)
						playSoundEntity(players[i]->entity, 242+rand()%4, 64 );
					stats[i]->GOLD += GOLDBAG_AMOUNT;
					if( i!=0 ) {
						if( multiplayer==SERVER ) {
							// send the client info on the gold it picked up
							strcpy((char *)net_packet->data,"GOLD");
							SDLNet_Write32(stats[i]->GOLD,&net_packet->data[4]);
							net_packet->address.host = net_clients[i-1].host;
							net_packet->address.port = net_clients[i-1].port;
							net_packet->len = 8;
							sendPacketSafe(net_sock, -1, net_packet, i-1);
						}
					}

					// message for item pickup
					if( GOLDBAG_AMOUNT==1 )
						messagePlayer(i,language[483]);
					else
						messagePlayer(i,language[484],GOLDBAG_AMOUNT);

					// remove gold entity
					list_RemoveNode(my->mynode);
					return;
				}
			}
		}
	} else {
		my->flags[NOUPDATE] = TRUE;
	}
}
Ejemplo n.º 14
0
void actItem(Entity* my)
{
	Item* item;
	int i;

	if ( multiplayer == CLIENT )
	{
		my->flags[NOUPDATE] = true;
		if ( ITEM_LIFE == 0 )
		{
			Entity* tempEntity = uidToEntity(clientplayer);
			if ( tempEntity )
			{
				if ( entityInsideEntity(my, tempEntity) )
				{
					my->parent = tempEntity->getUID();
				}
				else
				{
					node_t* node;
					for ( node = map.creatures->first; node != nullptr; node = node->next )
					{
						Entity* entity = (Entity*)node->element;
						if ( entity->behavior == &actPlayer || entity->behavior == &actMonster )
						{
							if ( entityInsideEntity(my, entity) )
							{
								my->parent = entity->getUID();
								break;
							}
						}
					}
				}
			}
			else
			{
				node_t* node;
				for ( node = map.creatures->first; node != nullptr; node = node->next )
				{
					Entity* entity = (Entity*)node->element;
					if ( entity->behavior == &actPlayer || entity->behavior == &actMonster )
					{
						if ( entityInsideEntity(my, entity) )
						{
							my->parent = entity->getUID();
							break;
						}
					}
				}
			}
		}

		// request entity update (check if I've been deleted)
		if ( ticks % (TICKS_PER_SECOND * 5) == my->getUID() % (TICKS_PER_SECOND * 5) )
		{
			strcpy((char*)net_packet->data, "ENTE");
			net_packet->data[4] = clientnum;
			SDLNet_Write32(my->getUID(), &net_packet->data[5]);
			net_packet->address.host = net_server.host;
			net_packet->address.port = net_server.port;
			net_packet->len = 9;
			sendPacketSafe(net_sock, -1, net_packet, 0);
		}
	}
	else
	{
		// select appropriate model
		my->skill[2] = -5;
		if ( my->itemSokobanReward != 1 )
		{
			my->flags[INVISIBLE] = false;
		}
		item = newItemFromEntity(my);
		my->sprite = itemModel(item);
		free(item);
	}
	//if( ITEM_LIFE==0 )
	//	playSoundEntityLocal( my, 149, 64 );
	ITEM_LIFE++;
	/*ITEM_AMBIENCE++;
	if( ITEM_AMBIENCE>=TICKS_PER_SECOND*30 ) {
		ITEM_AMBIENCE=0;
		playSoundEntityLocal( my, 149, 64 );
	}*/

	// pick up item
	if (multiplayer != CLIENT)
	{
		if ( my->isInteractWithMonster() )
		{
			Entity* monsterInteracting = uidToEntity(my->interactedByMonster);
			if ( monsterInteracting )
			{
				if ( my->skill[10] >= 0 && my->skill[10] < NUMITEMS )
				{
					if ( items[my->skill[10]].category == Category::FOOD && monsterInteracting->getMonsterTypeFromSprite() != SLIME )
					{
						monsterInteracting->monsterConsumeFoodEntity(my, monsterInteracting->getStats());
					}
					else
					{
						monsterInteracting->monsterAddNearbyItemToInventory(monsterInteracting->getStats(), 24, 9, my);
					}
				}
				my->clearMonsterInteract();
				return;
			}
			my->clearMonsterInteract();
		}
		for ( i = 0; i < MAXPLAYERS; i++)
		{
			if ((i == 0 && selectedEntity == my) || (client_selected[i] == my))
			{
				if (inrange[i])
				{
					if (players[i] != nullptr && players[i]->entity != nullptr)
					{
						playSoundEntity( players[i]->entity, 35 + rand() % 3, 64 );
					}
					Item* item2 = newItemFromEntity(my);
					if ( players[i] && players[i]->entity )
					{
						if ( my->itemStolen == 1 && item2 && (static_cast<Uint32>(item2->ownerUid) == players[i]->entity->getUID()) )
						{
							steamAchievementClient(i, "BARONY_ACH_REPOSSESSION");
						}
					}
					//messagePlayer(i, "old owner: %d", item2->ownerUid);
					if (item2)
					{
						item = itemPickup(i, item2);
						if (item)
						{
							if (i == 0)
							{
								free(item2);
							}
							int oldcount = item->count;
							item->count = 1;
							messagePlayer(i, language[504], item->description());
							item->count = oldcount;
							if (i != 0)
							{
								free(item);
							}
							my->removeLightField();
							list_RemoveNode(my->mynode);
							return;
						}
					}
				}
			}
		}
	}

	if ( my->itemNotMoving )
	{
		switch ( my->sprite )
		{
			case 610:
			case 611:
			case 612:
			case 613:
				my->spawnAmbientParticles(80, my->sprite - 4, 10 + rand() % 40, 1.0, false);
				if ( !my->light )
				{
					my->light = lightSphereShadow(my->x / 16, my->y / 16, 3, 192);
				}
				break;
			default:
				break;
		}
		if ( multiplayer == CLIENT )
		{
			// let the client process some more gravity and make sure it isn't stopping early at an awkward angle.
			if ( my->itemNotMovingClient == 1 )
			{
				return;
			}
		}
		else
		{
			return;
		}
	}

	// gravity
	bool onground = false;
	if ( my->z < 7.5 - models[my->sprite]->sizey * .25 )
	{
		// fall
		// chakram and shuriken lie flat, needs to use sprites for client
		if ( my->sprite == 567 || my->sprite == 569 )
		{
			// todo: adjust falling rates for thrown items if need be
			ITEM_VELZ += 0.04;
			my->z += ITEM_VELZ;
			my->roll += 0.08;
		}
		else
		{
			ITEM_VELZ += 0.04;
			my->z += ITEM_VELZ;
			my->roll += 0.04;
		}
	}
	else
	{
		if ( my->x >= 0 && my->y >= 0 && my->x < map.width << 4 && my->y < map.height << 4 )
		{
			if ( map.tiles[(int)(my->y / 16)*MAPLAYERS + (int)(my->x / 16)*MAPLAYERS * map.height] 
				|| (my->sprite >= 610 && my->sprite <= 613) )
			{
				// land
				ITEM_VELZ *= -.7;
				if ( ITEM_VELZ > -.35 )
				{
					// chakram and shuriken lie flat, needs to use sprites for client
					if ( my->sprite == 567 || my->sprite == 569 )
					{
						my->roll = PI;
						my->pitch = 0;
						if ( my->sprite == 569 )
						{
							my->z = 8.5 - models[my->sprite]->sizey * .25;
						}
						else
						{
							my->z = 8.75 - models[my->sprite]->sizey * .25;
						}
					}
					else
					{
						my->roll = PI / 2.0;
						my->z = 7.5 - models[my->sprite]->sizey * .25;
					}
					ITEM_VELZ = 0;
					onground = true;
				}
				else
				{
					onground = true;
					my->z = 7.5 - models[my->sprite]->sizey * .25 - .0001;
				}
			}
			else
			{
				// fall
				ITEM_VELZ += 0.04;
				my->z += ITEM_VELZ;
				my->roll += 0.04;
			}
		}
		else
		{
			// fall
			ITEM_VELZ += 0.04;
			my->z += ITEM_VELZ;
			my->roll += 0.04;
		}
	}

	// falling out of the map
	if ( my->z > 128 )
	{
		if ( ITEM_TYPE == ARTIFACT_MACE && my->parent != 0 )
		{
			steamAchievementEntity(uidToEntity(my->parent), "BARONY_ACH_STFU");
		}
		list_RemoveNode(my->mynode);
		return;
	}

	// don't perform unneeded computations on items that have basically no velocity
	double groundheight;
	if ( my->sprite == 569 )
	{
		groundheight = 8.5 - models[my->sprite]->sizey * .25;
	}
	else if ( my->sprite == 567 )
	{
		groundheight = 8.75 - models[my->sprite]->sizey * .25;
	}
	else
	{
		groundheight = 7.5 - models[my->sprite]->sizey * .25;
	}

	if ( onground && my->z > groundheight - .0001 && my->z < groundheight + .0001 && fabs(ITEM_VELX) < 0.02 && fabs(ITEM_VELY) < 0.02 )
	{
		my->itemNotMoving = 1;
		my->flags[UPDATENEEDED] = false;
		if ( multiplayer != CLIENT )
		{
			serverUpdateEntitySkill(my, 18); //update itemNotMoving flag
		}
		else
		{
			my->itemNotMovingClient = 1;
		}
		return;
	}

	// horizontal motion
	if ( ITEM_NOCOLLISION )
	{
		double newx = my->x + ITEM_VELX;
		double newy = my->y + ITEM_VELY;
		if ( !checkObstacle( newx, newy, my, NULL ) )
		{
			my->x = newx;
			my->y = newy;
			my->yaw += sqrt( ITEM_VELX * ITEM_VELX + ITEM_VELY * ITEM_VELY ) * .05;
		}
	}
	else
	{
		double result = clipMove(&my->x, &my->y, ITEM_VELX, ITEM_VELY, my);
		my->yaw += result * .05;
		if ( result != sqrt( ITEM_VELX * ITEM_VELX + ITEM_VELY * ITEM_VELY ) )
		{
			if ( !hit.side )
			{
				ITEM_VELX *= -.5;
				ITEM_VELY *= -.5;
			}
			else if ( hit.side == HORIZONTAL )
			{
				ITEM_VELX *= -.5;
			}
			else
			{
				ITEM_VELY *= -.5;
			}
		}
	}
	ITEM_VELX = ITEM_VELX * .925;
	ITEM_VELY = ITEM_VELY * .925;
}