void Thrower::playerThrowLitExplosive(const coord aimCell) { const int DYNAMITE_FUSE = eng->player->dynamiteFuseTurns; const int FLARE_FUSE = eng->player->flareFuseTurns; eng->player->explosiveThrown(); //Get flight path vector<coord> path = getFlightPath(eng->player->pos.x, eng->player->pos.y, aimCell.x, aimCell.y, false, false); //Render const char glyph = eng->itemData->itemDefinitions[item_dynamite]->glyph; sf::Color clr = DYNAMITE_FUSE != -1 ? clrRedLight : clrYellow; for(unsigned int i = 1; i < path.size() - 1; i++) { eng->renderer->drawMapAndInterface(false); if(eng->map->playerVision[path[i].x][path[i].y]) { eng->renderer->drawCharacter(glyph, renderArea_mainScreen, path[i].x, path[i].y, clr); eng->renderer->updateWindow(); eng->sleep(eng->config->DELAY_PROJECTILE_DRAW); } // eng->renderer->updateWindow(); } if(DYNAMITE_FUSE != -1) { eng->log->addMessage("I throw a lit dynamite stick."); if(eng->map->featuresStatic[path.back().x][path.back().y]->isBottomless() == false) { eng->featureFactory->spawnFeatureAt(feature_litDynamite, path.back(), new DynamiteSpawnData(DYNAMITE_FUSE)); } } else if(FLARE_FUSE != -1) { eng->log->addMessage("I throw a lit flare."); if(eng->map->featuresStatic[path.back().x][path.back().y]->isBottomless() == false) { eng->featureFactory->spawnFeatureAt(feature_litFlare, path.back(), new DynamiteSpawnData(FLARE_FUSE)); } eng->gameTime->updateLightMap(); eng->player->updateFov(); eng->renderer->drawMapAndInterface(); } else { eng->log->addMessage("I throw a lit Molotov Cocktail."); if(eng->map->featuresStatic[path.back().x][path.back().y]->isBottomless() == false) { // eng->audio->playSound(audio_molotovExplosion); eng->explosionMaker->runExplosion(path.back(), false, new StatusBurning(eng)); } } eng->gameTime->letNextAct(); }
LCreal AirVehicle::getFlightPathD() const { return ( (LCreal)Basic::Angle::R2DCC * getFlightPath() ); }
void Thrower::throwMissile(Actor* const actorThrowing, const coord aim) { Inventory* inventory = actorThrowing->getInventory(); Item* const itemStack = inventory->getItemInSlot(slot_missiles); if(itemStack != NULL) { const ItemDefinition& itemDefStack = itemStack->getDef(); //Get path vector<coord> path; const bool INCLUDE_BLOCKED_CELL = itemDefStack.isQuaffable; //potions may shatter against walls and affect them bool continueUntilSolid = false; Actor* const actorAtAimPos = eng->mapTests->getActorAtPos(aim); if(actorAtAimPos != NULL) { if(actorAtAimPos->getDef()->actorSize >= actorSize_humanoid) { continueUntilSolid = true; } } path = getFlightPath(actorThrowing->pos.x, actorThrowing->pos.y, aim.x, aim.y, INCLUDE_BLOCKED_CELL, continueUntilSolid); // Copy item stack to a new item, and decrease stack by 1 (possibly destroying it) Item* itemThrown = eng->itemFactory->copyItem(itemStack); itemThrown->numberOfItems = 1; const ItemDefinition& itemDefThrown = itemThrown->getDef(); inventory->decreaseItemInSlot(slot_missiles); // Print initial throwing message const string itemRef = eng->itemData->getItemRef(itemThrown, itemRef_a); if(actorThrowing == eng->player) { eng->log->clearLog(); eng->log->addMessage("I throw " + itemRef + "."); } else { if(eng->map->playerVision[path.front().x][path.front().y] == true) { eng->log->addMessage("I see " + actorThrowing->getNameThe() + " throw " + itemRef + "."); } } eng->renderer->drawMapAndInterface(true); int blockedInElement = -1; const int WPN_BASE_ABILITY = itemDefThrown.missileBaseAttackSkill; const int ACTOR_ABILITY = actorThrowing->getDef()->abilityValues.getAbilityValue(ability_accuracyRanged, true, *(actorThrowing)); const int TOTAL_ABILITY = WPN_BASE_ABILITY + ACTOR_ABILITY; const AbilityRollResult_t rollResult = eng->abilityRoll->roll(TOTAL_ABILITY); const DiceParam& dmg = itemDefThrown.missileDmg; const int DMG = rollResult == successCritical ? dmg.rolls * dmg.sides + dmg.plus : eng->dice(dmg.rolls, dmg.sides) + dmg.plus; const char glyph = itemThrown->getGlyph(); const sf::Color clr = itemThrown->getColor(); int chanceToDestroyItem = 0; //Run path, render, see what it hits (do dmg) for(unsigned int i = 1; i < path.size(); i++) { eng->renderer->drawMapAndInterface(false); Actor* const actorHere = eng->mapTests->getActorAtPos(path.at(i)); if(actorHere != NULL) { //If actor was aimed for if(path.at(i) == aim) { if(rollResult >= successSmall) { if(eng->map->playerVision[path.at(i).x][path.at(i).y]) { eng->renderer->drawCharacter('*', renderArea_mainScreen, path[i].x, path[i].y, clrRedLight); eng->renderer->updateWindow(); eng->sleep(eng->config->DELAY_PROJECTILE_DRAW * 4); } const sf::Color hitMessageClr = actorHere == eng->player ? clrMessageBad : clrMessageGood; eng->log->addMessage(actorHere->getNameThe() + " is hit.", hitMessageClr); actorHere->hit(DMG, damageType_physical); //TODO fix this if there ever is a non-physical thrown weapon //If the thing that hit an actor is a potion, let it make stuff happen... if(itemDefThrown.isQuaffable) { dynamic_cast<Potion*>(itemThrown)->collide(path.at(i), actorHere, itemDefThrown, eng); delete itemThrown; return; } blockedInElement = i; chanceToDestroyItem = 25; break; } } //If actor hit by accident if(actorHere->getDef()->actorSize >= actorSize_humanoid && eng->dice(1, 100) < 25) { if(eng->map->playerVision[path.at(i).x][path.at(i).y]) { eng->renderer->drawCharacter('*', renderArea_mainScreen, path.at(i).x, path.at(i).y, clrRedLight); eng->renderer->updateWindow(); eng->sleep(eng->config->DELAY_PROJECTILE_DRAW * 4); } const sf::Color hitMessageClr = actorHere == eng->player ? clrMessageBad : clrMessageGood; eng->log->addMessage(actorHere->getNameThe() + " is hit.", hitMessageClr); eng->renderer->drawMapAndInterface(); actorHere->hit(DMG / 2, damageType_physical); //TODO fix this if there ever is a non-physical thrown weapon //If the thing that hit an actor is a potion, let it make stuff happen... if(itemDefThrown.isQuaffable == true) { dynamic_cast<Potion*>(itemThrown)->collide(path.at(i), actorHere, itemDefThrown, eng); delete itemThrown; return; } blockedInElement = i; chanceToDestroyItem = 25; break; } } if(eng->map->playerVision[path[i].x][path[i].y]) { eng->renderer->drawCharacter(glyph, renderArea_mainScreen, path[i].x, path[i].y, clr); eng->renderer->updateWindow(); eng->sleep(eng->config->DELAY_PROJECTILE_DRAW); } } //If no actor blocked the potion, collide it on the landscape if(itemThrown->getDef().isQuaffable) { if(blockedInElement == -1) { dynamic_cast<Potion*>(itemThrown)->collide(path.back(), NULL, itemDefThrown, eng); delete itemThrown; return; } } if(eng->dice(1, 100) < chanceToDestroyItem) { delete itemThrown; } else { const int DROP_ELEMENT = blockedInElement == -1 ? path.size() - 1 : blockedInElement; const coord dropPos = path.at(DROP_ELEMENT); const MaterialType_t materialAtDropPos = eng->map->featuresStatic[dropPos.x][dropPos.y]->getMaterialType(); if(materialAtDropPos == materialType_hard) { const bool IS_ALERTING_MONSTERS = actorThrowing == eng->player; Sound sound(itemThrown->getDef().landOnHardSurfaceSoundMessage, true, dropPos, false, IS_ALERTING_MONSTERS); eng->soundEmitter->emitSound(sound); } eng->itemDrop->dropItemOnMap(dropPos, &itemThrown); } eng->renderer->drawMapAndInterface(); //End turn eng->gameTime->letNextAct(); } }