Beispiel #1
0
void actGate(Entity *my) {
	int i;

	if( multiplayer!=CLIENT ) {
		if (!my->skill[28])
			return; //Gate needs the mechanism powered state variable to be set.

		if (my->skill[28] == 2) {
			//Raise gate if it's closed.
			if (!GATE_STATUS) {
				GATE_STATUS = 1;
				playSoundEntity(my, 81, 64);
				serverUpdateEntitySkill(my,3);
			}
		} else {
			//Close gate if it's open.
			if (GATE_STATUS) {
				GATE_STATUS = 0;
				playSoundEntity(my, 82, 64);
				serverUpdateEntitySkill(my,3);
			}
		}
	} else {
		my->flags[NOUPDATE] = TRUE;
	}
	if (!GATE_INIT ) {
		GATE_INIT = 1;
		GATE_STARTHEIGHT = my->z;
		my->scalex = 1.01;
		my->scaley = 1.01;
		my->scalez = 1.01;
	}
	
	// rightclick message
	if( multiplayer!=CLIENT ) {
		for(i=0;i<MAXPLAYERS;i++) {
			if( (i==0 && selectedEntity==my) || (client_selected[i]==my) ) {
				if(inrange[i]) {
					messagePlayer(i,language[475]);
				}
			}
		}
	}

	if( !GATE_STATUS ) {
		//Closing gate.
		if( my->z < GATE_STARTHEIGHT ) {
			GATE_VELZ += .25;
			my->z = std::min(GATE_STARTHEIGHT, my->z + GATE_VELZ);
		} else {
			GATE_VELZ = 0;
		}
	} else {
		//Opening gate.
		if( my->z > GATE_STARTHEIGHT-12 ) {
			my->z = std::max(GATE_STARTHEIGHT-12, my->z - 0.25);
			
			// rattle the gate
			GATE_RATTLE = (GATE_RATTLE==0);
			if( GATE_RATTLE ) {
				my->x += .05;
				my->y += .05;
			} else {
				my->x -= .05;
				my->y -= .05;
			}
		} else {
			// reset the gate's position
			if( GATE_RATTLE ) {
				GATE_RATTLE = 0;
				my->x -= .05;
				my->y -= .05;
			}
		}
	}
	
	//Setting collision
	node_t *node;
	bool somebodyinside = FALSE;
	if( my->z > GATE_STARTHEIGHT-6 && my->flags[PASSABLE] ) {
		for( node=map.entities->first; node!=NULL; node=node->next ) {
			Entity *entity = (Entity *)node->element;
			if( entity==my || entity->flags[PASSABLE] || entity->sprite == 1 )
				continue;
			if( entityInsideEntity(my,entity) ) {
				somebodyinside = TRUE;
				break;
			}
		}
		if( !somebodyinside )
			my->flags[PASSABLE] = FALSE;
	} else if( my->z < GATE_STARTHEIGHT-9 && !my->flags[PASSABLE] ) {
		my->flags[PASSABLE] = TRUE;
	}
}
Beispiel #2
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;
}
Beispiel #3
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;
}