void identifyGUIIdentify(Item *item) { if (!item) return; if (item->identified) { messagePlayer(clientnum, language[319],item->getName()); return; } if (!identifygui_appraising) { item->identified = TRUE; messagePlayer(clientnum, language[320], item->description()); if (appraisal_timer > 0 && appraisal_item && appraisal_item == item->uid) { appraisal_timer = 0; appraisal_item = 0; } } else { //Appraising. messagePlayer(clientnum, language[321], item->description()); //Tick the timer in act player. //Once the timer hits zero, roll to see if the item is identified. //If it is identified, identify it and print out a message for the player. identifygui_appraising = FALSE; if( item->type!=GEM_GLASS ) appraisal_timer = (items[item->type].value * 60) / (stats[clientnum].PROFICIENCIES[PRO_APPRAISAL] + 1); // time in ticks until item is appraised else appraisal_timer = (1000 * 60) / (stats[clientnum].PROFICIENCIES[PRO_APPRAISAL] + 1); // time in ticks until item is appraised+- appraisal_timer = std::min(std::max(1,appraisal_timer),36000); appraisal_timermax = appraisal_timer; appraisal_item = item->uid; //printlog( "DEBUGGING: Appraisal timer = %i.\n", appraisal_timer); } identifygui_active = FALSE; }
void actLadder(Entity *my) { int playercount=0; double dist; int i, c; LADDER_AMBIENCE--; if( LADDER_AMBIENCE<=0 ) { LADDER_AMBIENCE = TICKS_PER_SECOND*30; playSoundEntityLocal( my, 149, 64 ); } // use ladder (climb) if( multiplayer!=CLIENT ) { for(i=0;i<MAXPLAYERS;i++) { if( (i==0 && selectedEntity==my) || (client_selected[i]==my) ) { if(inrange[i]) { for( c=0; c<MAXPLAYERS; c++ ) { if( client_disconnected[c] || players[c] == NULL ) continue; else playercount++; dist = sqrt( pow(my->x-players[c]->x,2) + pow(my->y-players[c]->y,2) ); if( dist > TOUCHRANGE ) { messagePlayer(i,language[505]); return; } } if( playercount==1 ) messagePlayer(i,language[506]); else messagePlayer(i,language[507]); loadnextlevel=TRUE; if( secretlevel ) { switch( currentlevel ) { case 3: for( c=0; c<MAXPLAYERS; c++ ) steamAchievementClient(c,"BARONY_ACH_THUNDERGNOME"); break; } } if( LADDER_SECRET ) secretlevel = (secretlevel==FALSE); // toggle level lists return; } } } } }
void equipSpell(spell_t* spell, int playernum) { if ( playernum == clientnum ) { selected_spell = spell; messagePlayer(playernum, language[442], spell->name); } }
void actLadderUp(Entity *my) { int i; LADDER_AMBIENCE--; if( LADDER_AMBIENCE<=0 ) { LADDER_AMBIENCE = TICKS_PER_SECOND*30; playSoundEntityLocal( my, 149, 64 ); } // use ladder if( multiplayer!=CLIENT ) { for(i=0;i<MAXPLAYERS;i++) { if( (i==0 && selectedEntity==my) || (client_selected[i]==my) ) { if(inrange[i]) { messagePlayer(i,language[508]); return; } } } } }
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; }
void actFountain(Entity *my) { Entity *entity; //messagePlayer(0, "actFountain()"); //TODO: Temporary mechanism testing code. /* if( multiplayer != CLIENT ) { if (my->skill[28]) { //All it does is change its sprite to sink if it's powered. if (my->skill[28] == 1) { my->sprite = 163; } else { my->sprite = 164; } } }*/ //****************END TEST CODE*************** //TODO: Sounds. // spray water if( my->skill[0] > 0 || ( !my->skill[2] && multiplayer == CLIENT ) ) { #define FOUNTAIN_AMBIENCE my->skill[7] FOUNTAIN_AMBIENCE--; if( FOUNTAIN_AMBIENCE<=0 ) { FOUNTAIN_AMBIENCE = TICKS_PER_SECOND*6; playSoundEntityLocal(my, 135, 32 ); } entity = spawnGib(my); entity->flags[INVISIBLE] = FALSE; entity->y -= 2; entity->z -= 8; entity->flags[SPRITE] = FALSE; entity->flags[NOUPDATE] = TRUE; entity->flags[UPDATENEEDED] = FALSE; entity->skill[4] = 7; entity->sprite = 4; entity->yaw = (rand()%360)*PI/180.0; entity->pitch = (rand()%360)*PI/180.0; entity->roll = (rand()%360)*PI/180.0; entity->vel_x = 0; entity->vel_y = 0; entity->vel_z = .25; entity->fskill[3] = 0.03; } // the rest of the function is server-side. if( multiplayer==CLIENT ) return; // makes the fountain stop spraying water on clients if( my->skill[0] <= 0 ) my->skill[2] = 1; else my->skill[2] = 0; //Using the fountain (TODO: Monsters using it?). int i; for (i = 0; i < MAXPLAYERS; ++i) { if ( (i==0 && selectedEntity==my) || (client_selected[i]==my) ) { if (inrange[i]) { //Act on it only if the player (or monster, if/when this is changed to support monster interaction?) is in range. //First check that it's not depleted. if (my->skill[0] == 0) { //Depleted messagePlayer(i, language[467]); } else { if (players[i]->entity->flags[BURNING]) { messagePlayer(i, language[468]); players[i]->entity->flags[BURNING] = FALSE; if (i > 0) serverUpdateEntityFlag(players[i]->entity, BURNING); } switch (my->skill[1]) { case 0: { playSoundEntity(players[i]->entity, 52, 64); //Spawn succubus. Uint32 color = SDL_MapRGB(mainsurface->format,255,128,0); messagePlayerColor(i, color, language[469]); summonMonster(SUCCUBUS, my->x, my->y); break; } case 1: messagePlayer(i, language[470]); messagePlayer(i, language[471]); playSoundEntity(players[i]->entity, 52, 64); stats[i]->HUNGER += 50; break; case 2: { //Potion effect. Potion effect is stored in my->skill[3], randomly chosen when the fountain is created. messagePlayer(i, language[470]); Item *item = newItem(static_cast<ItemType>(POTION_WATER+my->skill[3]), static_cast<Status>(4), 0,1,0,FALSE,NULL); useItem(item,i); // Long live the mystical fountain of TODO. break; } case 3: { // bless equipment playSoundEntity(players[i]->entity, 52, 64); Uint32 textcolor = SDL_MapRGB(mainsurface->format,0,255,255); messagePlayerColor(i, textcolor, language[471]); messagePlayer(i, language[473]); if( stats[i]->helmet ) stats[i]->helmet->beatitude++; if( stats[i]->breastplate ) stats[i]->breastplate->beatitude++; if( stats[i]->gloves ) stats[i]->gloves->beatitude++; if( stats[i]->shoes ) stats[i]->shoes->beatitude++; if( stats[i]->shield ) stats[i]->shield->beatitude++; if( stats[i]->weapon ) stats[i]->weapon->beatitude++; if( stats[i]->cloak ) stats[i]->cloak->beatitude++; if( stats[i]->amulet ) stats[i]->amulet->beatitude++; if( stats[i]->ring ) stats[i]->ring->beatitude++; if( stats[i]->mask ) stats[i]->mask->beatitude++; if( multiplayer==SERVER && i>0 ) { strcpy((char *)net_packet->data,"BLES"); net_packet->address.host = net_clients[i-1].host; net_packet->address.port = net_clients[i-1].port; net_packet->len = 4; sendPacketSafe(net_sock, -1, net_packet, i-1); } break; } default: break; } messagePlayer(i, language[474]); my->skill[0] = 0; //Dry up fountain. //TODO: messagePlayersInSight() instead. } //Then perform the effect randomly determined when the fountain was created. return; } } } }
void actFountain(Entity* my) { Entity* entity; //messagePlayer(0, "actFountain()"); //TODO: Temporary mechanism testing code. /* if( multiplayer != CLIENT ) { if (my->skill[28]) { //All it does is change its sprite to sink if it's powered. if (my->skill[28] == 1) { my->sprite = 163; } else { my->sprite = 164; } } }*/ //****************END TEST CODE*************** //TODO: Sounds. // spray water if ( my->skill[0] > 0 ) { #define FOUNTAIN_AMBIENCE my->skill[7] FOUNTAIN_AMBIENCE--; if ( FOUNTAIN_AMBIENCE <= 0 ) { FOUNTAIN_AMBIENCE = TICKS_PER_SECOND * 6; playSoundEntityLocal(my, 135, 32 ); } entity = spawnGib(my); entity->flags[INVISIBLE] = false; entity->y -= 2; entity->z -= 8; entity->flags[SPRITE] = false; entity->flags[NOUPDATE] = true; entity->flags[UPDATENEEDED] = false; entity->skill[4] = 7; entity->sprite = 4; entity->yaw = (rand() % 360) * PI / 180.0; entity->pitch = (rand() % 360) * PI / 180.0; entity->roll = (rand() % 360) * PI / 180.0; entity->vel_x = 0; entity->vel_y = 0; entity->vel_z = .25; entity->fskill[3] = 0.03; } // the rest of the function is server-side. if ( multiplayer == CLIENT ) { return; } //Using the fountain (TODO: Monsters using it?). int i; for (i = 0; i < MAXPLAYERS; ++i) { if ( (i == 0 && selectedEntity == my) || (client_selected[i] == my) ) { if (inrange[i]) //Act on it only if the player (or monster, if/when this is changed to support monster interaction?) is in range. { //First check that it's not depleted. if (my->skill[0] == 0) { //Depleted messagePlayer(i, language[467]); } else { if (players[i]->entity->flags[BURNING]) { messagePlayer(i, language[468]); players[i]->entity->flags[BURNING] = false; serverUpdateEntityFlag(players[i]->entity, BURNING); steamAchievementClient(i, "BARONY_ACH_HOT_SHOWER"); } switch (my->skill[1]) { case 0: { playSoundEntity(players[i]->entity, 52, 64); //Spawn succubus. Uint32 color = SDL_MapRGB(mainsurface->format, 255, 128, 0); Entity* spawnedMonster = nullptr; if ( !strncmp(map.name, "Underworld", 10) ) { Monster creature = SUCCUBUS; if ( rand() % 2 ) { creature = INCUBUS; } for ( int c = 0; spawnedMonster == nullptr && c < 5; ++c ) { switch ( c ) { case 0: spawnedMonster = summonMonster(creature, my->x, my->y); break; case 1: spawnedMonster = summonMonster(creature, my->x + 16, my->y); break; case 2: spawnedMonster = summonMonster(creature, my->x - 16, my->y); break; case 3: spawnedMonster = summonMonster(creature, my->x, my->y + 16); break; case 4: spawnedMonster = summonMonster(creature, my->x, my->y - 16); break; } } if ( spawnedMonster ) { if ( creature == INCUBUS ) { messagePlayerColor(i, color, language[2519]); Stat* tmpStats = spawnedMonster->getStats(); if ( tmpStats ) { strcpy(tmpStats->name, "lesser incubus"); } } else { messagePlayerColor(i, color, language[469]); } } } else if ( currentlevel < 10 ) { messagePlayerColor(i, color, language[469]); spawnedMonster = summonMonster(SUCCUBUS, my->x, my->y); } else if ( currentlevel < 20 ) { if ( rand() % 2 ) { spawnedMonster = summonMonster(INCUBUS, my->x, my->y); Stat* tmpStats = spawnedMonster->getStats(); if ( tmpStats ) { strcpy(tmpStats->name, "lesser incubus"); } messagePlayerColor(i, color, language[2519]); } else { messagePlayerColor(i, color, language[469]); spawnedMonster = summonMonster(SUCCUBUS, my->x, my->y); } } else { messagePlayerColor(i, color, language[2519]); spawnedMonster = summonMonster(INCUBUS, my->x, my->y); } break; } case 1: messagePlayer(i, language[470]); messagePlayer(i, language[471]); playSoundEntity(players[i]->entity, 52, 64); stats[i]->HUNGER += 100; players[i]->entity->modHP(5); break; case 2: { //Potion effect. Potion effect is stored in my->skill[3], randomly chosen when the fountain is created. messagePlayer(i, language[470]); Item* item = newItem(static_cast<ItemType>(POTION_WATER + my->skill[3]), static_cast<Status>(4), 0, 1, 0, false, NULL); useItem(item, i); // Long live the mystical fountain of TODO. break; } case 3: { // bless all equipment playSoundEntity(players[i]->entity, 52, 64); Uint32 textcolor = SDL_MapRGB(mainsurface->format, 0, 255, 255); messagePlayerColor(i, textcolor, language[471]); messagePlayer(i, language[473]); if ( stats[i]->helmet ) { stats[i]->helmet->beatitude++; } if ( stats[i]->breastplate ) { stats[i]->breastplate->beatitude++; } if ( stats[i]->gloves ) { stats[i]->gloves->beatitude++; } if ( stats[i]->shoes ) { stats[i]->shoes->beatitude++; } if ( stats[i]->shield ) { stats[i]->shield->beatitude++; } if ( stats[i]->weapon ) { stats[i]->weapon->beatitude++; } if ( stats[i]->cloak ) { stats[i]->cloak->beatitude++; } if ( stats[i]->amulet ) { stats[i]->amulet->beatitude++; } if ( stats[i]->ring ) { stats[i]->ring->beatitude++; } if ( stats[i]->mask ) { stats[i]->mask->beatitude++; } if ( multiplayer == SERVER && i > 0 ) { strcpy((char*)net_packet->data, "BLES"); net_packet->address.host = net_clients[i - 1].host; net_packet->address.port = net_clients[i - 1].port; net_packet->len = 4; sendPacketSafe(net_sock, -1, net_packet, i - 1); } break; } case 4: { // bless one piece of equipment playSoundEntity(players[i]->entity, 52, 64); Uint32 textcolor = SDL_MapRGB(mainsurface->format, 0, 255, 255); messagePlayerColor(i, textcolor, language[471]); //Choose only one piece of equipment to bless. //First, Figure out what equipment is available. std::vector<std::pair<Item*, Uint32>> items; if ( stats[i]->helmet ) { items.push_back(std::pair<Item*,int>(stats[i]->helmet, 0)); } if ( stats[i]->breastplate ) { items.push_back(std::pair<Item*,int>(stats[i]->breastplate, 1)); } if ( stats[i]->gloves ) { items.push_back(std::pair<Item*,int>(stats[i]->gloves, 2)); } if ( stats[i]->shoes ) { items.push_back(std::pair<Item*,int>(stats[i]->shoes, 3)); } if ( stats[i]->shield ) { items.push_back(std::pair<Item*,int>(stats[i]->shield, 4)); } if ( stats[i]->weapon ) { items.push_back(std::pair<Item*,int>(stats[i]->weapon, 5)); } if ( stats[i]->cloak ) { items.push_back(std::pair<Item*,int>(stats[i]->cloak, 6)); } if ( stats[i]->amulet ) { items.push_back(std::pair<Item*,int>(stats[i]->amulet, 7)); } if ( stats[i]->ring ) { items.push_back(std::pair<Item*,int>(stats[i]->ring, 8)); } if ( stats[i]->mask ) { items.push_back(std::pair<Item*,int>(stats[i]->mask, 9)); } if ( items.size() ) { messagePlayer(i, language[2592]); //"The fountain blesses a piece of equipment" //Randomly choose a piece of equipment. std::pair<Item*, Uint32> chosen = items[rand()%items.size()]; chosen.first->beatitude++; if ( multiplayer == SERVER && i > 0 ) { strcpy((char*)net_packet->data, "BLE1"); SDLNet_Write32(chosen.second, &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); } } //Does nothing if no valid items. break; } default: break; } messagePlayer(i, language[474]); my->skill[0] = 0; //Dry up fountain. serverUpdateEntitySkill(my, my->skill[0]); //TODO: messagePlayersInSight() instead. } //Then perform the effect randomly determined when the fountain was created. return; } } } }
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. }
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 Server::processInput(int connection, const std::string& input) { std::cout << "Connection " << connection << ": " << input << std::endl; try { Player temp = getPlayer(connection); if (input == "/quit") { unregisterPlayer(temp); std::cout << "Removed player on connection " << connection << std::endl; } else if (input == "/show") { if (temp.inGame() < 0) { messagePlayer(temp, "Invalid command, not in a game!"); } else { messagePlayer(temp, (myGameList[temp.inGame()].getBoard())); } } else if (input == "/list") { messagePlayer(temp, getPlayerList()); } else if (input == "/forfeit") { messagePlayer(temp, "Forfeit game message."); } else if (input.find("/play") == 0) { messagePlayer(temp, "Play game message."); std::stringstream ss(input); std::istream_iterator<std::string> it(ss); std::vector<std::string> tokens(it, std::istream_iterator<std::string>()); Player potential_p2; try { potential_p2 = getPlayer(tokens[1]); } catch(std::runtime_error&) { messagePlayer(temp, "No such player exists."); } if (potential_p2 == temp) { messagePlayer(temp, "No single player!"); } else if (potential_p2.inGame() != -1) { messagePlayer(temp, "That party is already in a game."); } else { messagePlayer(temp, "Creating game."); messagePlayer(potential_p2, temp.getName() + " started a game with you!"); } } else if (input == "/help") { messagePlayer(temp, "Valid commands: /help /list /show /quit /play /forfeit"); } else { #if 1 std::cout << "Broadcasting to lobby." << std::endl; for (auto it = myPlayerList.begin(); it != myPlayerList.end(); ++it) { if (it->second.inGame() < 0 && !(it->second == temp)) messagePlayer(it->second, temp.getName() + ": " + input); } #else std::cout << "Echoing message." << std::endl; messagePlayer(temp, temp.getName() + ": " + input); #endif } } catch(std::runtime_error&) // Probably because the player didn't exist! { // New player, this message should be the name. //myPlayerList.emplace(input, connection, input); myPlayerList[input] = Player(connection, input); std::cout << "Player created with name " << input << '.' << std::endl; messagePlayer(myPlayerList[input], "Username registered."); } }
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; } }
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 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 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; } }
void sellItemToShop(Item* item) { if ( !item ) { return; } if ( item->beatitude < 0 && itemIsEquipped(item, clientnum) ) { messagePlayer(clientnum, language[1124], item->getName()); playSound(90, 64); return; } bool deal = true; if ( stats[clientnum]->PROFICIENCIES[PRO_TRADING] >= CAPSTONE_UNLOCK_LEVEL[PRO_TRADING] ) { //Skill capstone: Can sell anything to any shop. } else { switch ( shopkeepertype ) { case 0: // arms & armor if ( itemCategory(item) != WEAPON && itemCategory(item) != ARMOR && itemCategory(item) != THROWN ) { deal = false; } break; case 1: // hats if ( itemCategory(item) != ARMOR ) { deal = false; } break; case 2: // jewelry if ( itemCategory(item) != RING && itemCategory(item) != AMULET && itemCategory(item) != GEM ) { deal = false; } break; case 3: // bookstore if ( itemCategory(item) != SPELLBOOK && itemCategory(item) != SCROLL && itemCategory(item) != BOOK ) { deal = false; } break; case 4: // potion shop if ( itemCategory(item) != POTION ) { deal = false; } break; case 5: // magicstaffs if ( itemCategory(item) != MAGICSTAFF ) { deal = false; } break; case 6: // food if ( itemCategory(item) != FOOD ) { deal = false; } break; case 7: // tools case 8: // lights if ( itemCategory(item) != TOOL && itemCategory(item) != THROWN ) { deal = false; } break; default: break; } } if ( !deal ) { shopspeech = language[212 + rand() % 3]; shoptimer = ticks - 1; playSound(90, 64); return; } if ( items[item->type].value * .75 <= item->sellValue(clientnum) ) { shopspeech = language[209 + rand() % 3]; } else { shopspeech = language[206 + rand() % 3]; } shoptimer = ticks - 1; newItem(item->type, item->status, item->beatitude, 1, item->appearance, item->identified, shopInv); stats[clientnum]->GOLD += item->sellValue(clientnum); playSound(89, 64); int ocount = item->count; item->count = 1; messagePlayer(clientnum, language[1125], item->description(), item->sellValue(clientnum)); item->count = ocount; if ( multiplayer != CLIENT ) { if ( rand() % 2 ) { if ( item->sellValue(clientnum) <= 1 ) { // selling 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 { strcpy((char*)net_packet->data, "SHPS"); SDLNet_Write32(shopkeeper, &net_packet->data[4]); // send item that was sold 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); sellitem = NULL; }
Entity* castSpell(Uint32 caster_uid, spell_t *spell, bool using_magicstaff, bool trap) { Entity *caster = uidToEntity(caster_uid); if (!caster || !spell) { //Need a spell and caster to cast a spell. return NULL; } Entity *result = NULL; //If the spell spawns an entity (like a magic light ball or a magic missile), it gets stored here and returned. #define spellcasting std::min(std::max(0,stat->PROFICIENCIES[PRO_SPELLCASTING]+statGetINT(stat)),100) //Shortcut! if (clientnum != 0 && multiplayer == CLIENT) { strcpy( (char *)net_packet->data, "SPEL" ); 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 NULL; } if (!spell->elements.first) { return NULL; } //node_t *node = spell->types->first; #define PROPULSION_MISSILE 1 int i = 0; int chance = 0; int propulsion = 0; int traveltime = 0; int magiccost = 0; int extramagic = 0; //Extra magic drawn in from the caster being a newbie. int extramagic_to_use = 0; //Instead of doing element->mana (which causes bugs), this is an extra factor in the mana equations. Pumps extra mana into elements from extramagic. Entity *entity = NULL; spell_t *channeled_spell=NULL; //Pointer to the spell if it's a channeled spell. For the purpose of giving it its node in the channeled spell list. node_t *node = spell->elements.first; stat_t *stat = caster->getStats(); int player = -1; for (i = 0; i < numplayers; ++i) { if (caster == players[i]) { player = i; //Set the player. } } bool newbie = FALSE; if( !using_magicstaff && !trap) { if (stat->PROFICIENCIES[PRO_SPELLCASTING] < SPELLCASTING_BEGINNER) { newbie = TRUE; //The caster has lower spellcasting skill. Cue happy fun times. } /*magiccost = getCostOfSpell(spell); if (magiccost < 0) { if (player >= 0) messagePlayer(player, "Error: Invalid spell. Mana cost is negative?"); return NULL; }*/ if (multiplayer == SINGLE) { magiccost = cast_animation.mana_left; caster->drainMP(magiccost); } else { magiccost = getCostOfSpell(spell); caster->drainMP(magiccost); } } if (newbie) { //So This wizard is a newbie. //First, drain some extra mana maybe. int chance = rand()%10; if (chance >= spellcasting/10) { //At skill 20, there's an 80% chance you'll use extra mana. At 70, there's a 30% chance. extramagic = rand()%(300/(spellcasting+1)); //Use up extra mana. More mana used the lower your spellcasting skill. extramagic = std::min(extramagic, stat->MP / 10); //To make sure it doesn't draw, say, 5000 mana. Cause dammit, if you roll a 1 here...you're doomed. caster->drainMP(extramagic); } //Now, there's a chance they'll fumble the spell. chance = rand()%10; if (chance >= spellcasting/10) { if (rand()%3 == 1) { //Fizzle the spell. //TODO: Cool effects. playSoundEntity(caster,163,128); if (player >= 0) messagePlayer(player, language[409]); return NULL; } } } //Check if the bugger is levitating. bool levitating = FALSE; if (!trap) { if (stat->EFFECTS[EFF_LEVITATING] == TRUE ) levitating=TRUE; if (stat->ring != NULL ) if (stat->ring->type == RING_LEVITATION ) levitating = TRUE; if (stat->shoes != NULL) if (stat->shoes->type == STEEL_BOOTS_LEVITATION ) levitating = TRUE; } //Water walking boots bool waterwalkingboots = FALSE; if (!trap) { if (stat->shoes != NULL) if (stat->shoes->type == IRON_BOOTS_WATERWALKING ) waterwalkingboots = TRUE; } node_t *node2; //For traversing the map looking for...liquids? //Check if swimming. if (!waterwalkingboots && !levitating && !trap && player>=0) { bool swimming=FALSE; if( players[player] ) { int x = std::min<int>(std::max(0.0,floor(caster->x/16)),map.width-1); int y = std::min<int>(std::max(0.0,floor(caster->y/16)),map.height-1); if( animatedtiles[map.tiles[y*MAPLAYERS+x*MAPLAYERS*map.height]] ) swimming=TRUE; } if( swimming ) { //Can't cast spells while swimming if not levitating or water walking. if (player >= 0) messagePlayer(player, language[410]); return NULL; } } //Right. First, grab the root element, which is what determines the delivery system. //spellElement_t *element = (spellElement_t *)spell->elements->first->element; spellElement_t *element = (spellElement_t *)node->element; if (element) { extramagic_to_use = 0; /*if (magiccost > stat->MP) { if (player >= 0) messagePlayer(player, "Insufficient mana!"); //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 NULL; }*/ if (extramagic > 0) { //Extra magic. Pump it in here? chance = rand()%5; if (chance == 1) { //Use some of that extra magic in this element. int amount = rand()%extramagic; extramagic -= amount; extramagic_to_use += amount; } } if (!strcmp(element->name, spellElement_missile.name)) { //Set the propulsion to missile. propulsion = PROPULSION_MISSILE; traveltime = element->duration; if (newbie) { //This guy's a newbie. There's a chance they've screwed up and negatively impacted the efficiency of the spell. chance = rand()%10; if (chance >= spellcasting/10) traveltime -= rand()%(1000/(spellcasting+1)); if (traveltime < 30) traveltime = 30; //Range checking. } traveltime += (((element->mana + extramagic_to_use) - element->base_mana) / element->overload_multiplier) * element->duration; } else if (!strcmp(element->name, spellElement_light.name)) { entity = newEntity(175, 1, map.entities); // black magic ball entity->parent = caster->uid; entity->x = caster->x; entity->y = caster->y; entity->z = -5.5 + ((-6.5f + -4.5f) / 2) * sin(0); entity->skill[7] = -5.5; //Base z. entity->sizex = 1; entity->sizey = 1; entity->yaw = caster->yaw; entity->flags[UPDATENEEDED]=TRUE; entity->flags[PASSABLE]=TRUE; entity->flags[BRIGHT]=TRUE; entity->behavior=&actMagiclightBall; entity->skill[4] = entity->x; //Store what x it started shooting out from the player at. entity->skill[5] = entity->y; //Store what y it started shooting out from the player at. entity->skill[12] = (element->duration * (((element->mana + extramagic_to_use) / element->base_mana) * element->overload_multiplier)); //How long this thing lives. node_t *spellnode = list_AddNodeLast(&entity->children); spellnode->element = copySpell(spell); //We need to save the spell since this is a channeled spell. channeled_spell = (spell_t*)(spellnode->element); spellnode->size = sizeof(spell_t); ((spell_t *)spellnode->element)->caster = caster->uid; if( using_magicstaff ) ((spell_t *)spellnode->element)->magicstaff = TRUE; spellnode->deconstructor = &spellDeconstructor; if (newbie) { //This guy's a newbie. There's a chance they've screwed up and negatively impacted the efficiency of the spell. chance = rand()%10; if (chance >= spellcasting/10) { // lifespan of the lightball entity->skill[12] -= rand()%(2000/(spellcasting+1)); if (entity->skill[12] < 180) entity->skill[12] = 180; //Range checking. } } if (using_magicstaff || trap) { entity->skill[12] = MAGICSTAFF_LIGHT_DURATION; //TODO: Grab the duration from the magicstaff or trap? ((spell_t *)spellnode->element)->sustain = FALSE; } else { entity->skill[12] /= getCostOfSpell((spell_t *)spellnode->element); } ((spell_t *)spellnode->element)->channel_duration = entity->skill[12]; //Tell the spell how long it's supposed to last so that it knows what to reset its timer to. result = entity; playSoundEntity(entity, 165, 128 ); } else if (!strcmp(element->name, spellElement_invisible.name)) { int duration = element->duration; duration += (((element->mana + extramagic_to_use) - element->base_mana) / element->overload_multiplier) * element->duration; node_t *spellnode = list_AddNodeLast(&caster->getStats()->magic_effects); spellnode->element = copySpell(spell); //We need to save the spell since this is a channeled spell. channeled_spell = (spell_t*)(spellnode->element); channeled_spell->magic_effects_node = spellnode; spellnode->size = sizeof(spell_t); ((spell_t *)spellnode->element)->caster = caster->uid; spellnode->deconstructor = &spellDeconstructor; if (newbie) { //This guy's a newbie. There's a chance they've screwed up and negatively impacted the efficiency of the spell. chance = rand()%10; if (chance >= spellcasting/10) duration -= rand()%(1000/(spellcasting+1)); if (duration < 180) duration = 180; //Range checking. } duration /= getCostOfSpell((spell_t *)spellnode->element); channeled_spell->channel_duration = duration; //Tell the spell how long it's supposed to last so that it knows what to reset its timer to. stat->EFFECTS[EFF_INVISIBLE] = TRUE; stat->EFFECTS_TIMERS[EFF_INVISIBLE] = duration; for (i = 0; i < numplayers; ++i) { if (caster == players[i]) { serverUpdateEffects(i); } } playSoundEntity(caster, 166, 128 ); spawnMagicEffectParticles(caster->x,caster->y,caster->z,174); } else if (!strcmp(element->name, spellElement_levitation.name)) { int duration = element->duration; duration += (((element->mana + extramagic_to_use) - element->base_mana) / element->overload_multiplier) * element->duration; node_t *spellnode = list_AddNodeLast(&caster->getStats()->magic_effects); spellnode->element = copySpell(spell); //We need to save the spell since this is a channeled spell. channeled_spell = (spell_t*)(spellnode->element); channeled_spell->magic_effects_node = spellnode; spellnode->size = sizeof(spell_t); ((spell_t *)spellnode->element)->caster = caster->uid; spellnode->deconstructor = &spellDeconstructor; if (newbie) { //This guy's a newbie. There's a chance they've screwed up and negatively impacted the efficiency of the spell. chance = rand()%10; if (chance >= spellcasting/10) duration -= rand()%(1000/(spellcasting+1)); if (duration < 180) duration = 180; //Range checking. } duration /= getCostOfSpell((spell_t *)spellnode->element); channeled_spell->channel_duration = duration; //Tell the spell how long it's supposed to last so that it knows what to reset its timer to. stat->EFFECTS[EFF_LEVITATING] = TRUE; stat->EFFECTS_TIMERS[EFF_LEVITATING] = duration; for (i = 0; i < numplayers; ++i) { if (caster == players[i]) { serverUpdateEffects(i); } } playSoundEntity(caster, 178, 128 ); spawnMagicEffectParticles(caster->x,caster->y,caster->z,170); } else if (!strcmp(element->name, spellElement_teleportation.name)) { caster->teleportRandom(); } else if (!strcmp(element->name, spellElement_identify.name)) { for (i = 0; i < numplayers; ++i) { if (caster == players[i]) { spawnMagicEffectParticles(caster->x,caster->y,caster->z,171); if (i != 0) { //Tell the client to identify an item. strcpy((char *)net_packet->data,"IDEN"); net_packet->address.host = net_clients[i - 1].host; net_packet->address.port = net_clients[i - 1].port; net_packet->len = 4; sendPacketSafe(net_sock, -1, net_packet, i-1); } else { //Identify an item. shootmode = FALSE; gui_mode = GUI_MODE_INVENTORY; //Reset the GUI to the inventory. identifygui_active = TRUE; identifygui_appraising = FALSE; //identifygui_mode = TRUE; } } } playSoundEntity(caster, 167, 128 ); } else if (!strcmp(element->name, spellElement_removecurse.name)) { for (i = 0; i < numplayers; ++i) { if (caster == players[i]) { spawnMagicEffectParticles(caster->x,caster->y,caster->z,169); if (i != 0) { //Tell the client to uncurse an item. strcpy((char *)net_packet->data,"RCUR"); net_packet->address.host = net_clients[i - 1].host; net_packet->address.port = net_clients[i - 1].port; net_packet->len = 4; sendPacketSafe(net_sock, -1, net_packet, i-1); } else { //Uncurse an item shootmode = FALSE; gui_mode = GUI_MODE_INVENTORY; //Reset the GUI to the inventory. removecursegui_active = TRUE; } } } playSoundEntity(caster, 167, 128 ); } else if (!strcmp(element->name, spellElement_magicmapping.name)) { for (i = 0; i < numplayers; ++i) { if (caster == players[i]) { spawnMagicEffectParticles(caster->x,caster->y,caster->z,171); spell_magicMap(i); } } playSoundEntity(caster, 167, 128 ); } else if (!strcmp(element->name, spellElement_heal.name)) { //TODO: Make it work for NPCs. for (i = 0; i < numplayers; ++i) { if (caster == players[i]) { int amount = element->damage * (((element->mana + extramagic_to_use) / element->base_mana) * element->overload_multiplier); //Amount to heal. if (newbie) { //This guy's a newbie. There's a chance they've screwed up and negatively impacted the efficiency of the spell. chance = rand()%10; if (chance >= spellcasting/10) amount -= rand()%(1000/(spellcasting+1)); if (amount < 8) amount = 8; //Range checking. } spell_changeHealth(players[i], amount); playSoundEntity(caster, 168, 128); for(node = map.entities->first; node->next; node = node->next) { entity = (Entity *)(node->element); if ( !entity || entity==caster ) continue; if( entity->behavior!=&actPlayer && entity->behavior!=&actMonster ) continue; if (entityDist(entity, caster) <= HEAL_RADIUS && entity->checkFriend(caster)) { spell_changeHealth(entity, amount); playSoundEntity(entity, 168, 128); spawnMagicEffectParticles(entity->x,entity->y,entity->z,169); } } break; } } playSoundEntity(caster, 168, 128); spawnMagicEffectParticles(caster->x,caster->y,caster->z,169); } else if (!strcmp(element->name, spellElement_cure_ailment.name)) { //TODO: Generalize it for NPCs too? for (i = 0; i < numplayers; ++i) { if (caster == players[i]) { Uint32 color = SDL_MapRGB(mainsurface->format,0,255,0); messagePlayerColor(i,color,language[411]); int c = 0; for (c = 0; c < NUMEFFECTS; ++c) { //This does a whole lot more than just cure ailments. stats[i].EFFECTS[c]=FALSE; stats[i].EFFECTS_TIMERS[c]=0; } serverUpdateEffects(player); playSoundEntity(entity, 168, 128); for(node = map.entities->first; node->next; node = node->next) { entity = (Entity *)(node->element); if( !entity || entity==caster ) continue; if( entity->behavior!=&actPlayer && entity->behavior!=&actMonster ) continue; stat_t *target_stat = entity->getStats(); if( target_stat ) { if (entityDist(entity, caster) <= HEAL_RADIUS && entity->checkFriend(caster)) { for (c = 0; c < NUMEFFECTS; ++c) { //This does a whole lot more than just cure ailments. target_stat->EFFECTS[c]=FALSE; target_stat->EFFECTS_TIMERS[c]=0; } if( entity->behavior==&actPlayer ) serverUpdateEffects(entity->skill[2]); if( entity->flags[BURNING] ) { entity->flags[BURNING] = FALSE; serverUpdateEntityFlag(entity,BURNING); } playSoundEntity(entity, 168, 128); spawnMagicEffectParticles(entity->x,entity->y,entity->z,169); } } } break; } } playSoundEntity(caster, 168, 128 ); spawnMagicEffectParticles(caster->x,caster->y,caster->z,169); } if (propulsion == PROPULSION_MISSILE) { entity = newEntity(168, 1, map.entities); // red magic ball entity->parent = caster->uid; entity->x = caster->x; entity->y = caster->y; entity->z = -1; entity->sizex = 1; entity->sizey = 1; entity->yaw = caster->yaw; entity->flags[UPDATENEEDED]=TRUE; entity->flags[PASSABLE]=TRUE; entity->flags[BRIGHT]=TRUE; entity->behavior = &actMagicMissile; double missile_speed = 4 * ((double)element->mana / element->overload_multiplier); //TODO: Factor in base mana cost? entity->vel_x = cos(entity->yaw) * (missile_speed); entity->vel_y = sin(entity->yaw) * (missile_speed); entity->skill[4] = 0; entity->skill[5] = traveltime; node = list_AddNodeFirst(&entity->children); node->element = copySpell(spell); ((spell_t *)node->element)->caster = caster->uid; node->deconstructor = &spellDeconstructor; node->size = sizeof(spell_t); if( !strcmp(spell->name, spell_fireball.name) ) playSoundEntity(entity, 164, 128 ); else if( !strcmp(spell->name, spell_lightning.name) ) playSoundEntity(entity, 171, 128 ); else if( !strcmp(spell->name, spell_cold.name) ) playSoundEntity(entity, 172, 128 ); else playSoundEntity(entity, 169, 128 ); result = entity; } extramagic_to_use = 0; if (extramagic > 0) { //Extra magic. Pump it in here? chance = rand()%5; if (chance == 1) { //Use some of that extra magic in this element. int amount = rand()%extramagic; extramagic -= amount; extramagic_to_use += amount; //TODO: Make the elements here use this? Looks like they won't, currently. Oh well. } } //TODO: Add the status/conditional elements/modifiers (probably best as elements) too. Like onCollision or something. //element = (spellElement_t *)element->elements->first->element; node = element->elements.first; if( node ) { element = (spellElement_t *)node->element; if (!strcmp(element->name, spellElement_force.name)) { //Give the spell force properties. if (propulsion == PROPULSION_MISSILE) { entity->sprite = 173; } if (newbie) { //This guy's a newbie. There's a chance they've screwed up and negatively impacted the efficiency of the spell. chance = rand()%10; if (chance >= spellcasting/10) element->damage -= rand()%(100/(spellcasting+1)); if (element->damage < 10) element->damage = 10; //Range checking. } } else if (!strcmp(element->name, spellElement_fire.name)) { if (propulsion == PROPULSION_MISSILE) { entity->sprite = 168; //entity->skill[4] = entity->x; //Store what x it started shooting out from the player at. //entity->skill[5] = entity->y; //Store what y it started shooting out from the player at. //entity->skill[12] = (100 * stat->PROFICIENCIES[PRO_SPELLCASTING]) + (100 * stat->PROFICIENCIES[PRO_MAGIC]) + (100 * (rand()%10)) + (10 * (rand()%10)) + (rand()%10); //How long this thing lives. //playSoundEntity( entity, 59, 128 ); } if (newbie) { //This guy's a newbie. There's a chance they've screwed up and negatively impacted the efficiency of the spell. chance = rand()%10; if (chance >= spellcasting/10) element->damage -= rand()%(100/(spellcasting+1)); if (element->damage < 10) element->damage = 10; //Range checking. } } else if (!strcmp(element->name, spellElement_lightning.name)) { if (propulsion == PROPULSION_MISSILE) { entity->sprite = 170; } if (newbie) { //This guy's a newbie. There's a chance they've screwed up and negatively impacted the efficiency of the spell. chance = rand()%10; if (chance >= spellcasting/10) element->damage -= rand()%(100/(spellcasting+1)); if (element->damage < 10) element->damage = 10; //Range checking. } } else if (!strcmp(element->name, spellElement_confuse.name)) { if (propulsion == PROPULSION_MISSILE) { entity->sprite = 173; } } else if (!strcmp(element->name, spellElement_cold.name)) { if (propulsion == PROPULSION_MISSILE) { entity->sprite = 172; } } else if (!strcmp(element->name, spellElement_dig.name)) { if (propulsion == PROPULSION_MISSILE) { entity->sprite = 171; } } else if (!strcmp(element->name, spellElement_locking.name)) { if (propulsion == PROPULSION_MISSILE) { entity->sprite = 171; } } else if (!strcmp(element->name, spellElement_opening.name)) { if (propulsion == PROPULSION_MISSILE) { entity->sprite = 171; } } else if (!strcmp(element->name, spellElement_slow.name)) { if (propulsion == PROPULSION_MISSILE) { entity->sprite = 171; } } else if (!strcmp(element->name, spellElement_sleep.name)) { if (propulsion == PROPULSION_MISSILE) { entity->sprite = 172; } } else if (!strcmp(spell->name, spell_magicmissile.name)) { if (propulsion == PROPULSION_MISSILE) { entity->sprite = 173; } } } } //Random chance to level up spellcasting skill. if(rand()%4==0) { caster->increaseSkill(PRO_SPELLCASTING); } if(rand()%5==0) { caster->increaseSkill(PRO_MAGIC); // otherwise you will basically never be able to learn all the spells in the game... } if (spell_isChanneled(spell) && !using_magicstaff) { //TODO: What about magic traps and channeled spells? if (!channeled_spell) { printlog( "What. Spell is channeled but no channeled_spell pointer? What sorcery is this?\n"); } else { int target_client = 0; for (i = 0; i < numplayers; ++i) { if (players[i] == caster) { target_client = i; } } //printlog( "Client is: %d\n", target_client); if (multiplayer == SERVER && target_client != 0) { strcpy( (char *)net_packet->data, "CHAN" ); net_packet->data[4] = clientnum; SDLNet_Write32(spell->ID, &net_packet->data[5]); net_packet->address.host = net_clients[target_client - 1].host; net_packet->address.port = net_clients[target_client - 1].port; net_packet->len = 9; sendPacketSafe(net_sock, -1, net_packet, target_client-1); } //Add this spell to the list of channeled spells. node = list_AddNodeLast(&channeledSpells[target_client]); node->element = channeled_spell; node->size = sizeof(spell_t); node->deconstructor = &emptyDeconstructor; channeled_spell->sustain_node = node; } } return result; }
void startTradingServer(Entity* entity, int player) { if (!entity) { return; } if ( multiplayer == CLIENT ) { return; } if (!players[player] || !players[player]->entity) { return; } Stat* stats = entity->getStats(); if ( stats == NULL ) { return; } if ( player == 0 ) { shootmode = false; gui_mode = GUI_MODE_SHOP; shopInv = &stats->inventory; shopkeeper = entity->getUID(); shoptimer = ticks - 1; shopspeech = language[194 + rand() % 3]; shopinventorycategory = 7; sellitem = NULL; Entity* entity = uidToEntity(shopkeeper); shopkeepertype = entity->monsterStoreType; shopkeepername = stats->name; shopitemscroll = 0; identifygui_active = false; closeRemoveCurseGUI(); //Initialize shop gamepad code here. if ( shopinvitems[0] != nullptr ) { selectedShopSlot = 0; warpMouseToSelectedShopSlot(); } else { selectedShopSlot = -1; } } else if ( multiplayer == SERVER ) { // open shop on client Stat* entitystats = entity->getStats(); strcpy((char*)net_packet->data, "SHOP"); SDLNet_Write32((Uint32)entity->getUID(), &net_packet->data[4]); net_packet->data[8] = entity->monsterStoreType; strcpy((char*)(&net_packet->data[9]), entitystats->name); net_packet->data[9 + strlen(entitystats->name)] = 0; net_packet->address.host = net_clients[player - 1].host; net_packet->address.port = net_clients[player - 1].port; net_packet->len = 9 + strlen(entitystats->name) + 1; sendPacketSafe(net_sock, -1, net_packet, player - 1); // fill client's shop inventory with items node_t* node; for ( node = entitystats->inventory.first; node != NULL; node = node->next ) { Item* item = (Item*)node->element; strcpy((char*)net_packet->data, "SHPI"); SDLNet_Write32(item->type, &net_packet->data[4]); net_packet->data[8] = (char)item->status; net_packet->data[9] = (char)item->beatitude; net_packet->data[10] = (unsigned char)item->count; SDLNet_Write32((Uint32)item->appearance, &net_packet->data[11]); if ( item->identified ) { net_packet->data[15] = 1; } else { net_packet->data[15] = 0; } net_packet->address.host = net_clients[player - 1].host; net_packet->address.port = net_clients[player - 1].port; net_packet->len = 16; sendPacketSafe(net_sock, -1, net_packet, player - 1); } } entity->skill[0] = 4; // talk state entity->skill[1] = players[player]->entity->getUID(); messagePlayer(player, language[1122], stats->name); }
void updateIdentifyGUI() { //if (openedChest[clientnum]) // return; //Cannot have the identify and chest GUIs open at the same time. SDL_Rect pos; node_t *node; int y, c; //Identify GUI. if (identifygui_active) { //Center the identify GUI. pos.x = IDENTIFY_GUI_X; pos.y = IDENTIFY_GUI_Y; drawImage(identifyGUI_img, NULL, &pos); //Buttons if( mousestatus[SDL_BUTTON_LEFT] ) { //Identify GUI scroll up button. if (omousey >= IDENTIFY_GUI_Y + 16 && omousey < IDENTIFY_GUI_Y + 52) { if (omousex >= IDENTIFY_GUI_X + (identifyGUI_img->w - 28) && omousex < IDENTIFY_GUI_X + (identifyGUI_img->w - 12)) { buttonclick = 7; identifyscroll--; mousestatus[SDL_BUTTON_LEFT] = 0; } } //Identify GUI scroll down button. else if (omousey >= IDENTIFY_GUI_Y + 52 && omousey < IDENTIFY_GUI_Y + 88) { if (omousex >= IDENTIFY_GUI_X + (identifyGUI_img->w - 28) && omousex < IDENTIFY_GUI_X + (identifyGUI_img->w - 12)) { buttonclick = 8; identifyscroll++; mousestatus[SDL_BUTTON_LEFT] = 0; } } else if (omousey >= IDENTIFY_GUI_Y && omousey < IDENTIFY_GUI_Y + 15) { //Identify GUI close button. if (omousex >= IDENTIFY_GUI_X + 393 && omousex < IDENTIFY_GUI_X + 407) { buttonclick = 9; mousestatus[SDL_BUTTON_LEFT] = 0; } if (omousex >= IDENTIFY_GUI_X && omousex < IDENTIFY_GUI_X + 377 && omousey >= IDENTIFY_GUI_Y && omousey < IDENTIFY_GUI_Y + 15) { gui_clickdrag = TRUE; dragging_identifyGUI = TRUE; dragoffset_x = omousex - IDENTIFY_GUI_X; dragoffset_y = omousey - IDENTIFY_GUI_Y; mousestatus[SDL_BUTTON_LEFT] = 0; } } } // mousewheel if( omousex>=IDENTIFY_GUI_X+12 && omousex<IDENTIFY_GUI_X+(identifyGUI_img->w-28) ) { if( omousey>=IDENTIFY_GUI_Y+16 && omousey<IDENTIFY_GUI_Y+(identifyGUI_img->h-8) ) { if( mousestatus[SDL_BUTTON_WHEELDOWN] ) { mousestatus[SDL_BUTTON_WHEELDOWN] = 0; identifyscroll++; } else if( mousestatus[SDL_BUTTON_WHEELUP] ) { mousestatus[SDL_BUTTON_WHEELUP] = 0; identifyscroll--; } } } if (dragging_identifyGUI) { if (gui_clickdrag) { identifygui_offset_x = (omousex - dragoffset_x) - (IDENTIFY_GUI_X - identifygui_offset_x); identifygui_offset_y = (omousey - dragoffset_y) - (IDENTIFY_GUI_Y - identifygui_offset_y); if (IDENTIFY_GUI_X <= camera.winx) identifygui_offset_x = camera.winx - (IDENTIFY_GUI_X - identifygui_offset_x); if (IDENTIFY_GUI_X > camera.winx + camera.winw - identifyGUI_img->w) identifygui_offset_x = (camera.winx + camera.winw - identifyGUI_img->w) - (IDENTIFY_GUI_X - identifygui_offset_x); if (IDENTIFY_GUI_Y <= camera.winy) identifygui_offset_y = camera.winy - (IDENTIFY_GUI_Y - identifygui_offset_y); if (IDENTIFY_GUI_Y > camera.winy + camera.winh - identifyGUI_img->h) identifygui_offset_y = (camera.winy + camera.winh - identifyGUI_img->h) - (IDENTIFY_GUI_Y - identifygui_offset_y); } else { dragging_identifyGUI = FALSE; } } list_t *identify_inventory = &stats[clientnum].inventory; if (!identify_inventory) { messagePlayer(0, "Warning: stats[%d].inventory is not a valid list. This should not happen.", clientnum); } else { //Print the window label signifying this as the identify GUI. //char *window_name = (char*)malloc(sizeof(char)); //strcpy(window_name, "Identify Item"); char *window_name; if (identifygui_appraising) window_name = language[317]; else window_name = language[318]; ttfPrintText(ttf8, (IDENTIFY_GUI_X + 2 + ((identifyGUI_img->w / 2) - ((TTF8_WIDTH * longestline(window_name)) / 2))), IDENTIFY_GUI_Y + 4, window_name); //Identify GUI up button. if (buttonclick == 7) { pos.x = IDENTIFY_GUI_X + (identifyGUI_img->w - 28); pos.y = IDENTIFY_GUI_Y + 16; pos.w = 0; pos.h = 0; drawImage(invup_bmp, NULL, &pos); } //Identify GUI down button. if (buttonclick == 8) { pos.x = IDENTIFY_GUI_X + (identifyGUI_img->w - 28); pos.y = IDENTIFY_GUI_Y + 52; pos.w = 0; pos.h = 0; drawImage(invdown_bmp, NULL, &pos); } //Identify GUI close button. if (buttonclick == 9) { pos.x = IDENTIFY_GUI_X + 393; pos.y = IDENTIFY_GUI_Y; pos.w = 0; pos.h = 0; drawImage(invclose_bmp, NULL, &pos); identifygui_active = FALSE; identifygui_appraising = FALSE; } Item *item = NULL; if (omousex >= IDENTIFY_GUI_X && omousex < IDENTIFY_GUI_X + (identifyGUI_img->w - 28)) { pos.x = IDENTIFY_GUI_X + 12; pos.w = 0; pos.h = 0; if (omousey >= IDENTIFY_GUI_Y + 16 && omousey < IDENTIFY_GUI_Y + 34) { //First inventory slot. pos.y = IDENTIFY_GUI_Y + 16; drawImage(inventoryoptionChest_bmp, NULL, &pos); if (mousestatus[SDL_BUTTON_LEFT]) { mousestatus[SDL_BUTTON_LEFT] = 0; identifyGUIIdentify(identify_items[0]); } } else if (omousey >= IDENTIFY_GUI_Y + 34 && omousey < IDENTIFY_GUI_Y + 52) { pos.y = IDENTIFY_GUI_Y + 34; drawImage(inventoryoptionChest_bmp, NULL, &pos); if (mousestatus[SDL_BUTTON_LEFT]) { mousestatus[SDL_BUTTON_LEFT]=0; identifyGUIIdentify(identify_items[1]); } } else if (omousey >= IDENTIFY_GUI_Y + 52 && omousey < IDENTIFY_GUI_Y + 70 ) { pos.y = IDENTIFY_GUI_Y + 52; drawImage(inventoryoptionChest_bmp, NULL, &pos); if( mousestatus[SDL_BUTTON_LEFT] ) { mousestatus[SDL_BUTTON_LEFT]=0; identifyGUIIdentify(identify_items[2]); } } else if (omousey >= IDENTIFY_GUI_Y + 70 && omousey < IDENTIFY_GUI_Y + 88) { pos.y = IDENTIFY_GUI_Y + 70; drawImage(inventoryoptionChest_bmp, NULL, &pos); if( mousestatus[SDL_BUTTON_LEFT] ) { mousestatus[SDL_BUTTON_LEFT]=0; identifyGUIIdentify(identify_items[3]); } } } //Okay, now prepare to render all the items. y = IDENTIFY_GUI_Y + 22; c = 0; if (identify_inventory) { for (node = identify_inventory->first; node != NULL; node = node->next) { item = (Item *) node->element; if (item && !item->identified) c++; } identifyscroll = std::max(0, std::min(identifyscroll, c - 4)); for (c = 0; c < 4; ++c) { identify_items[c] = NULL; } c = 0; //Actually render the items. for (node = identify_inventory->first; node != NULL; node = node->next) { if (node->element) { item = (Item *) node->element; if (item && !item->identified) { //Skip over all identified items. c++; if (c <= identifyscroll) continue; identify_items[c - identifyscroll - 1] = item; char tempstr[64] = { 0 }; strncpy(tempstr,item->description(),46); if( strlen(tempstr)==46 ) strcat(tempstr," ..."); ttfPrintText(ttf8,IDENTIFY_GUI_X+36,y,tempstr); pos.x = IDENTIFY_GUI_X + 16; pos.y = IDENTIFY_GUI_Y + 17 + 18 * (c - identifyscroll - 1); pos.w = 16; pos.h = 16; drawImageScaled(itemSprite(item), NULL, &pos); y += 18; if (c > 3 + identifyscroll) break; } } } } } } } //updateIdentifyGUI()
void actSwitch(Entity* my) { //TODO: If powered on, and it detects a depowered neighbor, it should pulse that neighbor to turn on. //Thus, this function needs to be called periodically. //This is so that if a switch goes off and there's another switch on the network, the entire network shuts off regardless of the other switch's status. //So then when that second switch's actSwitch() comes up, and if it's on, it'll repower the entire network -- which will stay powered until ALL connected switches go off. my->flags[PASSABLE] = true; // these should ALWAYS be passable. No exceptions if ( multiplayer != CLIENT ) { int i = 0; for (i = 0; i < MAXPLAYERS; ++i) { if ( (i == 0 && selectedEntity == my) || (client_selected[i] == my) ) { if (inrange[i]) //Act on it only if the player (or monster, if/when this is changed to support monster interaction?) is in range. { messagePlayer(i, language[1110]); playSoundEntity(my, 56, 64); my->toggleSwitch(); } } } if ( my->isInteractWithMonster() ) { my->toggleSwitch(); my->clearMonsterInteract(); } if (my->skill[0]) { //Power on any neighbors that don't have power. my->switchUpdateNeighbors(); //TODO: Alternatively, instead of using CPU cycles on this, have the recursive network shutdown alert any switches connected to it that are powered on that it's shutting down, so that they can repower the network come next frame. } } else { my->flags[NOUPDATE] = true; } // Rotate the switch when it is on/off. if ( my->skill[0] ) { if ( my->roll > -PI / 4 ) { my->roll -= std::max<real_t>((my->roll + PI / 4) / 2, .05); } else { my->roll = -PI / 4; } } else { if ( my->roll < PI / 4 ) { my->roll += std::max<real_t>(-(my->roll - PI / 4) / 2, .05); } else { my->roll = PI / 4; } } }
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); } } }
void actSwitchWithTimer(Entity* my) { my->flags[PASSABLE] = true; // these should ALWAYS be passable. No exceptions if ( multiplayer != CLIENT ) { int i = 0; for ( i = 0; i < MAXPLAYERS; ++i ) { if ( (i == 0 && selectedEntity == my) || (client_selected[i] == my) ) { // server/client has clicked on the entity. if ( inrange[i] ) //Act on it only if the player (or monster, if/when this is changed to support monster interaction?) is in range. { switch ( my->leverStatus ) { case 0: messagePlayer(i, language[2360]); break; case 1: messagePlayer(i, language[2361]); break; case 2: messagePlayer(i, language[2362]); break; default: messagePlayer(i, language[2363]); break; } if ( my->leverStatus < 3 ) { ++my->leverStatus; playSoundEntity(my, 248, 64); serverUpdateEntitySkill(my, 1); if ( my->leverStatus == 3 ) { playSoundEntity(my, 56, 64); my->toggleSwitch(); } } } } } if ( my->leverStatus == 4 ) { //Power on any neighbors that don't have power. my->switchUpdateNeighbors(); //TODO: Alternatively, instead of using CPU cycles on this, have the recursive network shutdown alert any switches connected to it that are powered on that it's shutting down, so that they can repower the network come next frame. } } else { my->flags[NOUPDATE] = true; } // Rotate the switch when it is on/off. if ( my->leverStatus == 0 ) { if ( my->roll > -PI / 4 ) { my->roll -= std::max<real_t>((my->roll + PI / 4) / 2, .05); } else { my->roll = -PI / 4; } } else if (my->leverStatus == 1 ) // 1/3 of the way up { if ( my->roll < -PI / 12 ) { my->roll += std::max<real_t>(-(my->roll + PI / 12) / 8, .02); } else { my->roll = -PI / 12; } } else if ( my->leverStatus == 2 ) // 2/3 of the way up { if ( my->roll < PI / 12 ) { my->roll += std::max<real_t>(-(my->roll - PI / 12) / 8, .02); } else { my->roll = PI / 12; } } else if ( my->leverStatus == 3 ) // all the way up { if ( my->roll < PI / 4 ) { my->roll += std::max<real_t>(-(my->roll - PI / 4) / 4, .02); } else { my->roll = PI / 4; if ( multiplayer != CLIENT ) { my->leverStatus = 4; serverUpdateEntitySkill(my, 1); } } } else if ( my->leverStatus == 4 ) // ticking down { if ( my->roll > -PI / 12 ) { my->roll -= (PI / 3) / static_cast<real_t>(my->leverTimerTicks); // move slowly towards 2/3rds of the resting point if ( my->ticks % 10 == 0 ) { playSoundEntityLocal(my, 247, 32); } } else { my->roll = -PI / 12; if ( multiplayer != CLIENT ) { playSoundEntity(my, 56, 64); my->leverStatus = 0; serverUpdateEntitySkill(my, 1); my->toggleSwitch(); } } } }
void consoleCommand(char *command_str) { node_t *node; Entity *entity; char name[64]; int c; if( !command_str ) return; if( !strncmp(command_str,"/ping",5) ) { if( multiplayer != CLIENT ) { messagePlayer(clientnum,language[1117],0); } else { strcpy((char *)net_packet->data,"PING"); net_packet->data[4] = clientnum; net_packet->address.host = net_server.host; net_packet->address.port = net_server.port; net_packet->len = 5; sendPacketSafe(net_sock, -1, net_packet, 0); pingtime = SDL_GetTicks(); } } else if (!strncmp(command_str, "/fov", 4)) { fov = atoi(&command_str[5]); fov = std::min(std::max<Uint32>(40,fov),100u); } else if (!strncmp(command_str, "/svflags ", 9)) { if( multiplayer==CLIENT ) { messagePlayer(clientnum,language[275]); } else { svFlags = atoi(&command_str[9]); messagePlayer(clientnum,language[276]); if( multiplayer==SERVER ) { // update client flags strcpy((char *)net_packet->data,"SVFL"); SDLNet_Write32(svFlags,&net_packet->data[4]); net_packet->len = 8; int c; for( c=1; c<MAXPLAYERS; c++ ) { if( client_disconnected[c] ) continue; net_packet->address.host = net_clients[c-1].host; net_packet->address.port = net_clients[c-1].port; sendPacketSafe(net_sock, -1, net_packet, c-1); messagePlayer(c,language[276]); } } } } else if( !strncmp(command_str,"/spawnitem ",11) ) { if( !(svFlags&SV_FLAG_CHEATS) ) { messagePlayer(clientnum,language[277]); return; } strcpy(name,command_str+11); for( c=0; c<NUMITEMS; c++ ) { if( strstr(items[c].name_identified, name) ) { dropItem(newItem(static_cast<ItemType>(c),EXCELLENT,0,1,rand(),TRUE,&stats[clientnum].inventory),0); break; } } if( c==NUMITEMS ) { messagePlayer(clientnum,language[278],name); } } else if( !strncmp(command_str,"/spawncursed ",13) ) { if( !(svFlags&SV_FLAG_CHEATS) ) { messagePlayer(clientnum,language[277]); return; } strcpy(name,command_str+13); for( c=0; c<NUMITEMS; c++ ) { if( strstr(items[c].name_identified, name) ) { dropItem(newItem(static_cast<ItemType>(c),WORN,-2,1,rand(),FALSE,&stats[clientnum].inventory),0); break; } } if( c==NUMITEMS ) { messagePlayer(clientnum,language[278],name); } } else if( !strncmp(command_str,"/kick ",6) ) { strcpy(name,command_str+6); if( multiplayer==SERVER ) { for( c=1; c<MAXPLAYERS; c++ ) { if( !client_disconnected[c] && !strncmp(name,stats[c].name,128) ) { client_disconnected[c] = TRUE; strcpy((char *)net_packet->data,"KICK"); net_packet->address.host = net_clients[c-1].host; net_packet->address.port = net_clients[c-1].port; net_packet->len = 4; sendPacketSafe(net_sock, -1, net_packet, c-1); int i; for( i=0; i<MAXPLAYERS; i++ ) { messagePlayer(i,language[279],c,stats[c].name); } break; } } if( c==MAXPLAYERS ) { messagePlayer(clientnum,language[280]); } } else if( multiplayer==CLIENT ) { messagePlayer(clientnum,language[281]); } else { messagePlayer(clientnum,language[282]); } } else if( !strncmp(command_str,"/spawnbook ",11) ) { if( !(svFlags&SV_FLAG_CHEATS) ) { messagePlayer(clientnum,language[277]); return; } strcpy(name,command_str+11); dropItem(newItem(READABLE_BOOK,EXCELLENT,0,1,getBook(name),TRUE,&stats[clientnum].inventory),0); } else if( !strncmp(command_str,"/savemap ",9) ) { if( command_str[9]!=0 ) { saveMap(command_str+9); messagePlayer(clientnum,language[283],command_str+9); } } else if( !strncmp(command_str,"/nextlevel",10) ) { if( !(svFlags&SV_FLAG_CHEATS) ) { messagePlayer(clientnum,language[277]); return; } if( multiplayer==CLIENT ) { messagePlayer(clientnum,language[284]); } else { messagePlayer(clientnum,language[285]); loadnextlevel=TRUE; } } else if( !strncmp(command_str,"/pos",4) ) { if( !(svFlags&SV_FLAG_CHEATS) ) { messagePlayer(clientnum,language[277]); return; } messagePlayer(clientnum,language[286],(int)camera.x,(int)camera.y,(int)camera.z,camera.ang,camera.vang); } else if( !strncmp(command_str,"/pathmap",4) ) { if( !(svFlags&SV_FLAG_CHEATS) ) { messagePlayer(clientnum,language[277]); return; } if( players[clientnum] ) { int x = std::min<int>(std::max(0.0,floor(players[clientnum]->x/16)),map.width-1); int y = std::min<int>(std::max(0.0,floor(players[clientnum]->y/16)),map.height-1); messagePlayer(clientnum,"pathMapGrounded value: %d",pathMapGrounded[y+x*map.height]); messagePlayer(clientnum,"pathMapFlying value: %d",pathMapFlying[y+x*map.height]); } } else if( !strncmp(command_str,"/exit",5) ) { mainloop=0; } else if( !strncmp(command_str,"/showfps",8) ) { showfps=(showfps==FALSE); } else if( !strncmp(command_str,"/noclip",7) ) { if( multiplayer!=SINGLE ) { messagePlayer(clientnum,language[287]); } else { noclip=(noclip==FALSE); if( noclip ) messagePlayer(clientnum,language[288]); else messagePlayer(clientnum,language[289]); } } else if( !strncmp(command_str,"/god",4) ) { if( multiplayer!=SINGLE ) { messagePlayer(clientnum,language[290]); } else { godmode=(godmode==FALSE); if( godmode ) messagePlayer(clientnum,language[291]); else messagePlayer(clientnum,language[292]); } } else if( !strncmp(command_str,"/buddha",7) ) { if( multiplayer!=SINGLE ) { messagePlayer(clientnum,language[293]); } else { buddhamode=(buddhamode==FALSE); if( buddhamode ) messagePlayer(clientnum,language[294]); else messagePlayer(clientnum,language[295]); } } else if( !strncmp(command_str,"/friendly",9) ) { if( !(svFlags&SV_FLAG_CHEATS) ) { messagePlayer(clientnum,language[277]); return; } if( multiplayer==CLIENT ) { messagePlayer(clientnum,language[284]); return; } everybodyfriendly=(everybodyfriendly==FALSE); if( everybodyfriendly ) messagePlayer(clientnum,language[296]); else messagePlayer(clientnum,language[297]); } else if( !strncmp(command_str,"/dowse",6) ) { if( !(svFlags&SV_FLAG_CHEATS) ) { messagePlayer(clientnum,language[277]); return; } for( node=map.entities->first; node!=NULL; node=node->next ) { entity = (Entity *)node->element; if( entity->behavior == &actLadder ) messagePlayer(clientnum,language[298],(int)(entity->x/16),(int)(entity->y/16)); } } else if( !strncmp(command_str,"/thirdperson",12) ) { if( !(svFlags&SV_FLAG_CHEATS) ) { messagePlayer(clientnum,language[277]); return; } if( players[clientnum] != NULL ) { players[clientnum]->skill[3]=(players[clientnum]->skill[3]==0); if( players[clientnum]->skill[3]==1 ) messagePlayer(clientnum,"thirdperson ON"); else messagePlayer(clientnum,"thirdperson OFF"); } } else if( !strncmp(command_str,"/res ",5) ) { xres = atoi(&command_str[5]); for( c=0; c<strlen(command_str); c++ ) { if( command_str[c] == 'x' ) { yres = atoi(&command_str[c+1]); break; } } } else if( !strncmp(command_str,"/rscale",7) ) { rscale = atoi(&command_str[8]); } else if( !strncmp(command_str,"/smoothlighting",15) ) { smoothlighting = (smoothlighting==0); } else if( !strncmp(command_str,"/fullscreen",11) ) { fullscreen = (fullscreen==0); } else if( !strncmp(command_str,"/shaking",8) ) { shaking = (shaking==0); } else if( !strncmp(command_str,"/bobbing",8) ) { bobbing = (bobbing==0); } else if( !strncmp(command_str,"/sfxvolume",10) ) { sfxvolume = atoi(&command_str[11]); } else if( !strncmp(command_str,"/musvolume",10) ) { musvolume = atoi(&command_str[11]); } else if( !strncmp(command_str,"/bind",5) ) { if( strstr(command_str,"IN_FORWARD") ) { impulses[IN_FORWARD] = atoi(&command_str[6]); printlog("Bound IN_FORWARD: %d\n",atoi(&command_str[6])); } else if( strstr(command_str,"IN_LEFT") ) { impulses[IN_LEFT] = atoi(&command_str[6]); printlog("Bound IN_LEFT: %d\n",atoi(&command_str[6])); } else if( strstr(command_str,"IN_BACK") ) { impulses[IN_BACK] = atoi(&command_str[6]); printlog("Bound IN_BACK: %d\n",atoi(&command_str[6])); } else if( strstr(command_str,"IN_RIGHT") ) { impulses[IN_RIGHT] = atoi(&command_str[6]); printlog("Bound IN_RIGHT: %d\n",atoi(&command_str[6])); } else if( strstr(command_str,"IN_TURNL") ) { impulses[IN_TURNL] = atoi(&command_str[6]); printlog("Bound IN_TURNL: %d\n",atoi(&command_str[6])); } else if( strstr(command_str,"IN_TURNR") ) { impulses[IN_TURNR] = atoi(&command_str[6]); printlog("Bound IN_TURNR: %d\n",atoi(&command_str[6])); } else if( strstr(command_str,"IN_UP") ) { impulses[IN_UP] = atoi(&command_str[6]); printlog("Bound IN_UP: %d\n",atoi(&command_str[6])); } else if( strstr(command_str,"IN_DOWN") ) { impulses[IN_DOWN] = atoi(&command_str[6]); printlog("Bound IN_DOWN: %d\n",atoi(&command_str[6])); } else if( strstr(command_str,"IN_CHAT") ) { impulses[IN_CHAT] = atoi(&command_str[6]); printlog("Bound IN_CHAT: %d\n",atoi(&command_str[6])); } else if( strstr(command_str,"IN_COMMAND") ) { impulses[IN_COMMAND] = atoi(&command_str[6]); printlog("Bound IN_COMMAND: %d\n",atoi(&command_str[6])); } else if( strstr(command_str,"IN_STATUS") ) { impulses[IN_STATUS] = atoi(&command_str[6]); printlog("Bound IN_STATUS: %d\n",atoi(&command_str[6])); } else if (strstr(command_str, "IN_SPELL_LIST")) { impulses[IN_SPELL_LIST] = atoi(&command_str[6]); printlog( "Bound IN_SPELL_LIST: %d\n", atoi(&command_str[6])); } else if (strstr(command_str, "IN_CAST_SPELL")) { impulses[IN_CAST_SPELL] = atoi(&command_str[6]); printlog( "Bound IN_CAST_SPELL: %d\n", atoi(&command_str[6])); } else if (strstr(command_str, "IN_DEFEND")) { impulses[IN_DEFEND] = atoi(&command_str[6]); printlog( "Bound IN_DEFEND: %d\n", atoi(&command_str[6])); } else if (strstr(command_str, "IN_ATTACK")) { impulses[IN_ATTACK] = atoi(&command_str[6]); printlog( "Bound IN_ATTACK: %d\n", atoi(&command_str[6])); } else if (strstr(command_str, "IN_USE")) { impulses[IN_USE] = atoi(&command_str[6]); printlog( "Bound IN_USE: %d\n", atoi(&command_str[6])); } else { messagePlayer(clientnum,"Invalid binding."); } } else if( !strncmp(command_str,"/mousespeed",11) ) { mousespeed = atoi(&command_str[12]); } else if( !strncmp(command_str,"/reversemouse",13) ) { reversemouse = (reversemouse==0); } else if( !strncmp(command_str,"/smoothmouse",12) ) { smoothmouse = (smoothmouse==FALSE); } else if( !strncmp(command_str,"/mana", 4) ) { if( multiplayer == SINGLE ) { stats[clientnum].MP = stats[clientnum].MAXMP; } else { messagePlayer(clientnum,language[299]); } } else if( !strncmp(command_str,"/heal", 4) ) { if( multiplayer == SINGLE ) { stats[clientnum].HP = stats[clientnum].MAXHP; } else { messagePlayer(clientnum,language[299]); } } else if (!strncmp(command_str, "/ip ", 4)) { if( command_str[4]!=0 ) { strcpy(last_ip, command_str + 4); last_ip[strlen(last_ip)-1]=0; } } else if (!strncmp(command_str, "/port ", 6)) { if (command_str[6] != 0) { strcpy(last_port, command_str + 6); last_port[strlen(last_port)-1]=0; } } else if (!strncmp(command_str, "/noblood", 8)) { spawn_blood = (spawn_blood==FALSE); } else if(!strncmp(command_str, "/colorblind", 11)) { colorblind = (colorblind==FALSE); } else if (!strncmp(command_str, "/gamma", 6)) { std::stringstream ss; ss << command_str + 7; ss >> vidgamma; }
void actPortal(Entity *my) { int playercount=0; double dist; int i, c; if( !PORTAL_INIT ) { PORTAL_INIT=1; my->light = lightSphereShadow(my->x/16,my->y/16,3,255); } PORTAL_AMBIENCE--; if( PORTAL_AMBIENCE<=0 ) { PORTAL_AMBIENCE = TICKS_PER_SECOND*2; playSoundEntityLocal( my, 154, 128 ); } my->yaw += 0.01; // rotate slowly on my axis my->sprite = 254+(my->ticks/20)%4; // animate if( multiplayer==CLIENT ) return; // step through portal for(i=0;i<MAXPLAYERS;i++) { if( (i==0 && selectedEntity==my) || (client_selected[i]==my) ) { if(inrange[i]) { for( c=0; c<MAXPLAYERS; c++ ) { if( client_disconnected[c] || players[c] == NULL ) continue; else playercount++; dist = sqrt( pow(my->x-players[c]->x,2) + pow(my->y-players[c]->y,2) ); if( dist > TOUCHRANGE ) { messagePlayer(i,language[505]); return; } } if( playercount==1 ) messagePlayer(i,language[510]); else messagePlayer(i,language[511]); loadnextlevel=TRUE; if( secretlevel ) { switch( currentlevel ) { case 9: { ; bool visiblegrave=FALSE; node_t *node; for( node=map.entities->first; node!=NULL; node=node->next ) { Entity *entity = (Entity *)node->element; if( entity->sprite==224 && !entity->flags[INVISIBLE] ) { visiblegrave=TRUE; break; } } if( visiblegrave ) for( c=0; c<MAXPLAYERS; c++ ) steamAchievementClient(c,"BARONY_ACH_ROBBING_THE_CRADLE"); break; } case 14: for( c=0; c<MAXPLAYERS; c++ ) steamAchievementClient(c,"BARONY_ACH_THESEUS_LEGACY"); break; } } if( !PORTAL_NOTSECRET ) secretlevel = (secretlevel==FALSE); // toggle level lists return; } } } }
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 actWinningPortal(Entity *my) { int playercount=0; double dist; int i, c; if( multiplayer!=CLIENT ) { if( my->flags[INVISIBLE] ) { node_t *node; for( node=map.entities->first; node!=NULL; node=node->next ) { Entity *entity = (Entity *)node->element; if( entity->behavior==&actMonster ) { Stat *stats = entity->getStats(); if( stats ) { if( stats->type == LICH || stats->type == DEVIL ) { return; } } } } my->flags[INVISIBLE] = FALSE; } } else { if( my->flags[INVISIBLE] ) return; } if( !PORTAL_INIT ) { PORTAL_INIT=1; my->light = lightSphereShadow(my->x/16,my->y/16,3,255); } PORTAL_AMBIENCE--; if( PORTAL_AMBIENCE<=0 ) { PORTAL_AMBIENCE = TICKS_PER_SECOND*2; playSoundEntityLocal( my, 154, 128 ); } my->yaw += 0.01; // rotate slowly on my axis my->sprite = 278+(my->ticks/20)%4; // animate if( multiplayer==CLIENT ) return; // step through portal for(i=0;i<MAXPLAYERS;i++) { if( (i==0 && selectedEntity==my) || (client_selected[i]==my) ) { if(inrange[i]) { for( c=0; c<MAXPLAYERS; c++ ) { if( client_disconnected[c] || players[c] == NULL ) continue; else playercount++; dist = sqrt( pow(my->x-players[c]->x,2) + pow(my->y-players[c]->y,2) ); if( dist > TOUCHRANGE ) { messagePlayer(i,language[509]); return; } } victory = PORTAL_VICTORYTYPE; if( multiplayer==SERVER ) { for( c=0; c<MAXPLAYERS; c++ ) { if( client_disconnected[c]==TRUE ) continue; strcpy((char *)net_packet->data,"WING"); net_packet->data[4] = victory; net_packet->address.host = net_clients[c-1].host; net_packet->address.port = net_clients[c-1].port; net_packet->len = 8; sendPacketSafe(net_sock, -1, net_packet, c-1); } } subwindow=0; introstage=5; // prepares win game sequence fadeout=TRUE; if( !intro ) pauseGame(2,FALSE); return; } } } }
void actHeadstone(Entity* my) { if ( my->flags[INVISIBLE] ) { if ( multiplayer != CLIENT ) { node_t* node; int goldbags = 0; bool artifact = false; for ( node = map.entities->first; node != nullptr; node = node->next ) { Entity* entity = (Entity*)node->element; if ( entity->sprite == 130 ) // gold bag { ++goldbags; } if ( entity->sprite == 508 ) { artifact = true; } } if ( goldbags >= 9 && artifact ) { return; } my->flags[INVISIBLE] = false; my->flags[PASSABLE] = false; serverUpdateEntityFlag(my, INVISIBLE); serverUpdateEntityFlag(my, PASSABLE); } else { return; } } HEADSTONE_AMBIENCE--; if ( HEADSTONE_AMBIENCE <= 0 ) { HEADSTONE_AMBIENCE = TICKS_PER_SECOND * 30; playSoundEntityLocal( my, 149, 32 ); } if ( multiplayer == CLIENT ) { return; } if ( !HEADSTONE_INIT ) { HEADSTONE_INIT = 1; HEADSTONE_MESSAGE = rand(); HEADSTONE_GHOUL = (rand() % 4 == 0); } bool shouldspawn = false; // rightclick message int i; if ( multiplayer != CLIENT ) { for (i = 0; i < MAXPLAYERS; i++) { if ( (i == 0 && selectedEntity == my) || (client_selected[i] == my) ) { if (inrange[i]) { messagePlayer(i, language[485 + HEADSTONE_MESSAGE % 17]); if ( HEADSTONE_GHOUL && !HEADSTONE_FIRED ) { shouldspawn = true; Uint32 color = SDL_MapRGB(mainsurface->format, 255, 128, 0); messagePlayerColor(i, color, language[502]); } } } } } // received on signal if ( my->skill[28] == 2 || shouldspawn ) { if ( !HEADSTONE_FIRED ) { HEADSTONE_FIRED = 1; // make a ghoul Entity* monster = summonMonster(GHOUL, my->x, my->y); if ( monster ) { monster->z = 13; if ( currentlevel >= 15 || !strncmp(map.name, "The Haunted Castle", 18) ) { Stat* tmpStats = monster->getStats(); if ( tmpStats ) { strcpy(tmpStats->name, "enslaved ghoul"); } } } } } }
void clickDescription(int player, Entity *entity) { stat_t *stat; Item *item; Uint32 uidnum; if( entity==NULL ) { if( !(*inputPressed(impulses[IN_ATTACK])) || shootmode ) return; if( omousex<camera.winx || omousex>=camera.winx+camera.winw || omousey<camera.winy || omousey>=camera.winy+camera.winh ) return; if (openedChest[clientnum]) if (omousex > CHEST_INVENTORY_X && omousex < CHEST_INVENTORY_X + inventoryChest_bmp->w && omousey > CHEST_INVENTORY_Y && omousey < CHEST_INVENTORY_Y + inventoryChest_bmp->h) return; //Click falls inside the chest inventory GUI. if (identifygui_active) if (omousex > IDENTIFY_GUI_X && omousex < IDENTIFY_GUI_X + identifyGUI_img->w && omousey > IDENTIFY_GUI_Y && omousey < IDENTIFY_GUI_Y + identifyGUI_img->h) return; //Click falls inside the identify item gui. if (book_open) if (mouseInBounds(BOOK_GUI_X, BOOK_GUI_X + bookgui_img->w, BOOK_GUI_Y, BOOK_GUI_Y + bookgui_img->h)) return; //Click falls inside the book GUI. if (gui_mode == GUI_MODE_INVENTORY || gui_mode == GUI_MODE_SHOP) { if( gui_mode == GUI_MODE_INVENTORY ) if (mouseInBounds(RIGHTSIDEBAR_X, RIGHTSIDEBAR_X + rightsidebar_titlebar_img->w, RIGHTSIDEBAR_Y, RIGHTSIDEBAR_Y + rightsidebar_height)) return; //Click falls inside the right sidebar. //int x = std::max(character_bmp->w, xres/2-inventory_bmp->w/2); //if (mouseInBounds(x,x+inventory_bmp->w,0,inventory_bmp->h)) //return NULL; if( mouseInBounds(INVENTORY_STARTX,INVENTORY_STARTX+INVENTORY_SIZEX*INVENTORY_SLOTSIZE,INVENTORY_STARTY,INVENTORY_STARTY+INVENTORY_SIZEY*INVENTORY_SLOTSIZE) ) { // clicked in inventory return; } if( gui_mode == GUI_MODE_SHOP ) { int x1 = xres/2-SHOPWINDOW_SIZEX/2, x2 = xres/2+SHOPWINDOW_SIZEX/2; int y1 = yres/2-SHOPWINDOW_SIZEY/2, y2 = yres/2+SHOPWINDOW_SIZEY/2; if (mouseInBounds(x1,x2,y1,y2)) return; } } else if (gui_mode == GUI_MODE_MAGIC) { if (magic_GUI_state == 0) { //Right, now calculate the spell list's height (the same way it calculates it for itself). int height = spell_list_titlebar_bmp->h; int numspells = 0; node_t *node; for (node = spellList.first; node != NULL; node = node->next) { numspells++; } int maxSpellsOnscreen = camera.winh / spell_list_gui_slot_bmp->h; numspells = std::min(numspells, maxSpellsOnscreen); height += numspells * spell_list_gui_slot_bmp->h; int spelllist_y = camera.winy + ((camera.winh / 2) - (height / 2)) + magicspell_list_offset_x; if (mouseInBounds(MAGICSPELL_LIST_X, MAGICSPELL_LIST_X + spell_list_titlebar_bmp->w, spelllist_y, spelllist_y + height)) return; } } if (mouseInBounds(0,224,0,420)) // character sheet return; int x = xres/2-(status_bmp->w/2); if (mouseInBounds(x,x+status_bmp->w,yres-status_bmp->h-hotbar_img->h,yres)) return; *inputPressed(impulses[IN_ATTACK])=0; if( softwaremode ) { entity = clickmap[omousey+omousex*yres]; } else { GLubyte pixel[4]; glReadPixels(omousex,yres-omousey,1,1,GL_RGBA,GL_UNSIGNED_BYTE,(void *)pixel); uidnum = pixel[0] + (((Uint32)pixel[1])<<8) + (((Uint32)pixel[2])<<16) + (((Uint32)pixel[3])<<24); entity = uidToEntity(uidnum); } } if( entity != NULL ) { if( multiplayer != CLIENT ) { if( (stat=entity->getStats())==NULL ) { Entity *parent = uidToEntity(entity->parent); if( entity->behavior==&actPlayerLimb || entity->skill[2]==entity->parent ) { if( parent ) { if( parent->behavior==&actPlayer || parent->behavior==&actMonster ) { stat_t *stats = parent->getStats(); if( stats ) { if( strcmp(stats->name,"") ) { messagePlayer(player,language[253],language[90+stats->type],stats->name); } else { messagePlayer(player,language[254],language[90+stats->type]); } } } } } else if( entity->behavior==&actTorch ) { messagePlayer(player,language[255]); } else if( entity->behavior==&actDoor ) { messagePlayer(player,language[256]); } else if( entity->behavior==&actItem ) { item = newItem(static_cast<ItemType>(entity->skill[10]),static_cast<Status>(entity->skill[11]),entity->skill[12],entity->skill[13],entity->skill[14],FALSE,NULL); if (item) { messagePlayer(player,language[257],item->description()); free(item); } } else if( entity->behavior==&actGoldBag ) { if( entity->skill[0]==1 ) messagePlayer(player,language[258]); else messagePlayer(player,language[259],entity->skill[0]); } else if( entity->behavior==&actCampfire) { messagePlayer(player,language[260]); } else if( entity->behavior==&actFountain) { messagePlayer(player,language[262]); } else if( entity->behavior==&actSink) { messagePlayer(player,language[263]); } else if( entity->behavior==&actLadder) { messagePlayer(player,language[264]); } else if( entity->behavior==&actLadderUp) { messagePlayer(player,language[265]); } else if( entity->behavior==&actChest || entity->behavior==&actChestLid ) { messagePlayer(player,language[266]); } else if( entity->behavior==&actGate) { messagePlayer(player,language[267]); } else if( entity->behavior==&actSpearTrap) { messagePlayer(player,language[268]); } else if( entity->behavior==&actSwitch) { messagePlayer(player,language[269]); } else if( entity->behavior==&actBoulder ) { messagePlayer(player,language[270]); } else if( entity->behavior==&actHeadstone ) { messagePlayer(player,language[271]); } else if( entity->behavior==&actPortal || entity->behavior==&actWinningPortal ) { messagePlayer(player,language[272]); } else if( entity->behavior==&actFurniture ) { if( entity->skill[0] ) messagePlayer(player,language[273]); else messagePlayer(player,language[274]); } } else { if( !strcmp(stat->name,"") ) { messagePlayer(player,language[254],language[90+stat->type]); } else { messagePlayer(player,language[253],language[90+stat->type],stat->name); } } } else { // send spot command to server strcpy((char *)net_packet->data,"SPOT"); net_packet->data[4]=player; SDLNet_Write32((Uint32)entity->uid,&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); } } }