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; }
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); } }
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); }
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]); } } } } } }
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; }