Пример #1
0
bool addSpell(int spell, int player, bool ignoreSkill)
{
	node_t* node = nullptr;

	// this is a local function
	if ( player != clientnum )
	{
		return false;
	}

	spell_t* new_spell = nullptr;

	switch ( spell )
	{
		case SPELL_FORCEBOLT:
			new_spell = copySpell(&spell_forcebolt);
			break;
		case SPELL_MAGICMISSILE:
			new_spell = copySpell(&spell_magicmissile);
			break;
		case SPELL_COLD:
			new_spell = copySpell(&spell_cold);
			break;
		case SPELL_FIREBALL:
			new_spell = copySpell(&spell_fireball);
			break;
		case SPELL_LIGHTNING:
			new_spell = copySpell(&spell_lightning);
			break;
		case SPELL_REMOVECURSE:
			new_spell = copySpell(&spell_removecurse);
			break;
		case SPELL_LIGHT:
			new_spell = copySpell(&spell_light);
			break;
		case SPELL_IDENTIFY:
			new_spell = copySpell(&spell_identify);
			break;
		case SPELL_MAGICMAPPING:
			new_spell = copySpell(&spell_magicmapping);
			break;
		case SPELL_SLEEP:
			new_spell = copySpell(&spell_sleep);
			break;
		case SPELL_CONFUSE:
			new_spell = copySpell(&spell_confuse);
			break;
		case SPELL_SLOW:
			new_spell = copySpell(&spell_slow);
			break;
		case SPELL_OPENING:
			new_spell = copySpell(&spell_opening);
			break;
		case SPELL_LOCKING:
			new_spell = copySpell(&spell_locking);
			break;
		case SPELL_LEVITATION:
			new_spell = copySpell(&spell_levitation);
			break;
		case SPELL_INVISIBILITY:
			new_spell = copySpell(&spell_invisibility);
			break;
		case SPELL_TELEPORTATION:
			new_spell = copySpell(&spell_teleportation);
			break;
		case SPELL_HEALING:
			new_spell = copySpell(&spell_healing);
			break;
		case SPELL_EXTRAHEALING:
			new_spell = copySpell(&spell_extrahealing);
			break;
		case SPELL_CUREAILMENT:
			new_spell = copySpell(&spell_cureailment);
			break;
		case SPELL_DIG:
			new_spell = copySpell(&spell_dig);
			break;
		case SPELL_STONEBLOOD:
			new_spell = copySpell(&spell_stoneblood);
			break;
		case SPELL_BLEED:
			new_spell = copySpell(&spell_bleed);
			break;
		case SPELL_SUMMON:
			new_spell = copySpell(&spell_summon);
			break;
		case SPELL_DOMINATE:
			new_spell = copySpell(&spell_dominate);
			break;
		case SPELL_REFLECT_MAGIC:
			new_spell = copySpell(&spell_reflectMagic);
			break;
		case SPELL_ACID_SPRAY:
			new_spell = copySpell(&spell_acidSpray);
			break;
		case SPELL_STEAL_WEAPON:
			new_spell = copySpell(&spell_stealWeapon);
			break;
		case SPELL_DRAIN_SOUL:
			new_spell = copySpell(&spell_drainSoul);
			break;
		case SPELL_VAMPIRIC_AURA:
			new_spell = copySpell(&spell_vampiricAura);
			break;
		case SPELL_CHARM_MONSTER:
			new_spell = copySpell(&spell_charmMonster);
			break;
		default:
			return false;
	}
	if ( spellInList(&spellList, new_spell) )
	{
		messagePlayer(player, language[439], new_spell->name);
		spellDeconstructor((void*)new_spell);
		return false;
	}
	if ( !ignoreSkill && stats[player]->PROFICIENCIES[PRO_MAGIC] + statGetINT(stats[player]) < new_spell->difficulty )
	{
		messagePlayer(player, language[440]);
		spellDeconstructor((void*)new_spell);
		return false;
	}
	messagePlayer(player, language[441], new_spell->name);
	node = list_AddNodeLast(&spellList);
	node->element = new_spell;
	node->size = sizeof(spell_t);
	node->deconstructor = &spellDeconstructor;

	players[player]->entity->increaseSkill(PRO_MAGIC);

	Item* item = newItem(SPELL_ITEM, SERVICABLE, 0, 1, spell, true, nullptr);
	itemPickup(player, item);
	free(item);

	return true;
}
Пример #2
0
void buyItemFromShop(Item* item)
{
	if ( !item )
	{
		return;
	}

	if ( stats[clientnum]->GOLD >= item->buyValue(clientnum) )
	{
		if ( items[item->type].value * 1.5 >= item->buyValue(clientnum) )
		{
			shopspeech = language[200 + rand() % 3];
		}
		else
		{
			shopspeech = language[197 + rand() % 3];
		}
		shoptimer = ticks - 1;
		Item* itemToPickup = newItem(item->type, item->status, item->beatitude, 1, item->appearance, item->identified, nullptr);
		itemPickup(clientnum, itemToPickup);

		stats[clientnum]->GOLD -= item->buyValue(clientnum);
		playSound(89, 64);
		int ocount = item->count;
		item->count = 1;
		messagePlayer(clientnum, language[1123], item->description(), item->buyValue(clientnum));
		item->count = ocount;
		if ( multiplayer != CLIENT )
		{
			Entity* entity = uidToEntity(shopkeeper);
			if (entity)
			{
				Stat* shopstats = entity->getStats();
				shopstats->GOLD += item->buyValue(clientnum);
			}
			if ( rand() % 2 )
			{
				if ( item->buyValue(clientnum) <= 1 )
				{
					// buying cheap items does not increase trading past basic
					if ( stats[clientnum]->PROFICIENCIES[PRO_TRADING] < SKILL_LEVEL_SKILLED )
					{
						players[clientnum]->entity->increaseSkill(PRO_TRADING);
					}
				}
				else
				{
					players[clientnum]->entity->increaseSkill(PRO_TRADING);
				}
			}
			else if ( item->buyValue(clientnum) >= 150 )
			{
				if ( item->buyValue(clientnum) >= 300 || rand() % 2 )
				{
					players[clientnum]->entity->increaseSkill(PRO_TRADING);
				}
			}
		}
		else
		{
			strcpy((char*)net_packet->data, "SHPB");
			SDLNet_Write32(shopkeeper, &net_packet->data[4]);

			// send item that was bought to server
			SDLNet_Write32(item->type, &net_packet->data[8]);
			SDLNet_Write32(item->status, &net_packet->data[12]);
			SDLNet_Write32(item->beatitude, &net_packet->data[16]);
			SDLNet_Write32((Uint32)item->appearance, &net_packet->data[20]);
			if ( item->identified )
			{
				net_packet->data[24] = 1;
			}
			else
			{
				net_packet->data[24] = 0;
			}
			net_packet->data[25] = clientnum;
			net_packet->address.host = net_server.host;
			net_packet->address.port = net_server.port;
			net_packet->len = 26;
			sendPacketSafe(net_sock, -1, net_packet, 0);
		}
		consumeItem(item);
	}
	else
	{
		shopspeech = language[203 + rand() % 3];
		shoptimer = ticks - 1;
		playSound(90, 64);
	}
}
Пример #3
0
void addSpell(int spell, int player) {
	node_t *node = NULL;

	// this is a local function
	if( player != clientnum )
		return;

	spell_t *new_spell = NULL;

	switch( spell ) {
		case SPELL_FORCEBOLT:
			new_spell = copySpell(&spell_forcebolt);
			break;
		case SPELL_MAGICMISSILE:
			new_spell = copySpell(&spell_magicmissile);
			break;
		case SPELL_COLD:
			new_spell = copySpell(&spell_cold);
			break;
		case SPELL_FIREBALL:
			new_spell = copySpell(&spell_fireball);
			break;
		case SPELL_LIGHTNING:
			new_spell = copySpell(&spell_lightning);
			break;
		case SPELL_REMOVECURSE:
			new_spell = copySpell(&spell_removecurse);
			break;
		case SPELL_LIGHT:
			new_spell = copySpell(&spell_light);
			break;
		case SPELL_IDENTIFY:
			new_spell = copySpell(&spell_identify);
			break;
		case SPELL_MAGICMAPPING:
			new_spell = copySpell(&spell_magicmapping);
			break;
		case SPELL_SLEEP:
			new_spell = copySpell(&spell_sleep);
			break;
		case SPELL_CONFUSE:
			new_spell = copySpell(&spell_confuse);
			break;
		case SPELL_SLOW:
			new_spell = copySpell(&spell_slow);
			break;
		case SPELL_OPENING:
			new_spell = copySpell(&spell_opening);
			break;
		case SPELL_LOCKING:
			new_spell = copySpell(&spell_locking);
			break;
		case SPELL_LEVITATION:
			new_spell = copySpell(&spell_levitation);
			break;
		case SPELL_INVISIBILITY:
			new_spell = copySpell(&spell_invisibility);
			break;
		case SPELL_TELEPORTATION:
			new_spell = copySpell(&spell_teleportation);
			break;
		case SPELL_HEALING:
			new_spell = copySpell(&spell_healing);
			break;
		case SPELL_EXTRAHEALING:
			new_spell = copySpell(&spell_extrahealing);
			break;
		case SPELL_CUREAILMENT:
			new_spell = copySpell(&spell_cureailment);
			break;
		case SPELL_DIG:
			new_spell = copySpell(&spell_dig);
			break;
		default:
			return;
	}
	if( spellInList(&spellList, new_spell) ) {
		messagePlayer(player, language[439],new_spell->name);
		spellDeconstructor((void *)new_spell);
		return;
	}
	if( stats[player]->PROFICIENCIES[PRO_MAGIC]+statGetINT(stats[player]) < new_spell->difficulty ) {
		messagePlayer(player, language[440]);
		spellDeconstructor((void *)new_spell);
		return;
	}
	messagePlayer(player,language[441],new_spell->name);
	node = list_AddNodeLast(&spellList);
	node->element = new_spell;
	node->size = sizeof(spell_t);
	node->deconstructor = &spellDeconstructor;

	players[player]->entity->increaseSkill(PRO_MAGIC);

	Item *item = newItem(SPELL_ITEM, SERVICABLE, 0, 1, spell, TRUE, NULL);
	itemPickup(player, item);
	free(item);
}
Пример #4
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]);
					}
				}
			}
		}
	}
}
Пример #5
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;
}