//---------------------------------------------------------------------------- IDestination * CBuildingTest::getRandomDestination() { CBuildingManager * bm = CBuildingManager::getInstance(); nlassert( bm ); IDestination * dest = NULL; do { sint32 randomNumber = RandomGenerator.rand( (uint16)bm->_Triggers.size()-1 ); CHashMap<sint,CBuildingManager::CTrigger>::iterator itTrigger = bm->_Triggers.begin(); for (sint32 i = 0; i < randomNumber; i++) { ++itTrigger; if (itTrigger == bm->_Triggers.end()) itTrigger = bm->_Triggers.begin(); } const sint triggerId = (*itTrigger).first; CBuildingManager::CTrigger & trigger = (*itTrigger).second; if (trigger.Destinations.empty()) { nlwarning("*** BuildingUnitTest *** trigger %u has no destination.", triggerId); continue; } randomNumber = RandomGenerator.rand( (uint16)trigger.Destinations.size()-1 ); dest = trigger.Destinations[randomNumber]; } while ( !dest ); return dest; }
//----------------------------------------------- bool CTimedAction::testCancelOnHit( sint32 attackSkillValue, CEntityBase * attacker, CEntityBase * defender) { // get defender defense skill sint32 defenderValue; if ( defender->getId().getType() == RYZOMID::player ) { CCharacter *pC = dynamic_cast<CCharacter*> (defender); if (!pC) { nlwarning("Entity %s type is player but dynamic_cast in CCharacter * returns NULL ?!", defender->getId().toString().c_str()); return false; } defenderValue = pC->getSkillValue(pC->getBestSkill()); } else { const CStaticCreatures * form = defender->getForm(); if ( !form ) { nlwarning( "<MAGIC>invalid creature form %s in entity %s", defender->getType().toString().c_str(), defender->getId().toString().c_str() ); return false; } defenderValue = form->getAttackLevel(); } //test if the spell is broken const uint8 chances = CStaticSuccessTable::getSuccessChance( SUCCESS_TABLE_TYPE::BreakCastResist, defenderValue - attackSkillValue); const uint8 roll = (uint8) RandomGenerator.rand(99); if ( roll >= chances ) return true; else return false; }
//---------------------------------------------------------------------------- void CBuildingTest::moveCharacter(uint charIndex) { nlassert( charIndex < TestCharacters.size() ); if ( !TestCharacters[charIndex].InBuilding ) { enterBuilding( charIndex ); } else { const bool leave = (RandomGenerator.rand(99) & 1); if (leave) leaveBuilding( charIndex ); else changeRoom( charIndex ); } }
//---------------------------------------------------------------------------- void CBuildingTest::timerCallback(CTimer * timer) { H_AUTO(BuildingTestTimerEvent); if (Verbose) { nlinfo("*** BuildingUnitTest *** callback count %u", _Count); } const uint randomNumber = (uint) RandomGenerator.rand( (uint16)TestCharacters.size()-1 ); for (uint i = 0; i < _Simultaneous; i++) { checkIntegrity(); const uint charIndex = (randomNumber + i) % TestCharacters.size(); moveCharacter( charIndex ); } checkIntegrity(); setNextEvent( timer ); }
//-------------------------------------------------------------- // CBounceEffect::getTargetForBounce() //-------------------------------------------------------------- CEntityBase *CBounceEffect::getTargetForBounce(CEntityBase *actor) const { // get entities around if (!_AffectedEntity) _AffectedEntity = CEntityBaseManager::getEntityBasePtr(_TargetRowId); if (!_AffectedEntity) return NULL; // get entities in surrouding area // range of the effect in meters = _Value CRangeSelector entitiesSelector; entitiesSelector.buildDisc( CEntityBaseManager::getEntityBasePtr(getCreatorRowId()), _AffectedEntity->getX(), _AffectedEntity->getY(), (float) _Value, EntityMatrix, true ); // select valid entities const vector<CEntityBase*> &entities = entitiesSelector.getEntities(); const uint size = (uint)entities.size(); vector<CEntityBase*> selectedEntities; selectedEntities.reserve(size); for (uint i = 0; i < entities.size() ; ++i) { if ( entities[i] && ( entities[i] != (CEntityBase*)(_AffectedEntity) ) && isEntityValidTarget(entities[i], actor) ) { selectedEntities.push_back(entities[i]); } } if (selectedEntities.empty()) return NULL; uint32 num = RandomGenerator.rand((uint16)selectedEntities.size()-1); return selectedEntities[num]; } // getTargetForBounce //
// mark a bnp file without corrupting its datas (this force the patch to be applied the next time the client is launched, thus delaying the trouble maker) static void markBNPFile(std::string &path) { CRandom rnd; rnd.srand((sint32) CTime::getLocalTime()); uint32 nFileSize=CFile::getFileSize(path); if (!nFileSize) return; FILE *f = fopen(path.c_str(), "rb+"); if (!f) return; // Result if (nlfseek64 (f, nFileSize-4, SEEK_SET) != 0) { fclose (f); return; } uint32 nOffsetFromBeginning; if (fread (&nOffsetFromBeginning, sizeof(uint32), 1, f) != 1) { fclose (f); return; } #ifdef NL_BIG_ENDIAN NLMISC_BSWAP32(nOffsetFromBeginning); #endif if (nlfseek64 (f, nOffsetFromBeginning, SEEK_SET) != 0) { fclose (f); return; } // Read the file count uint32 nNbFile; if (fread (&nNbFile, sizeof(uint32), 1, f) != 1) { fclose (f); return; } #ifdef NL_BIG_ENDIAN NLMISC_BSWAP32(nNbFile); #endif for (uint32 i = 0; i < nNbFile; ++i) { char FileName[MAX_PATH]; uint8 nStringSize; if (fread (&nStringSize, 1, 1, f) != 1) { fclose(f); return; } sint64 currPos = nlftell64(f); if (currPos < 0) { fclose(f); return; } if (fread (FileName, 1, nStringSize, f) != nStringSize) { fclose (f); return; } FileName[nStringSize] = 0; for(uint k = 0; k < nStringSize; ++k) { if (rnd.rand() & 1) FileName[k] = toupper(FileName[k]); else FileName[k] = tolower(FileName[k]); } if (nlfseek64 (f, currPos, SEEK_SET) != 0) { fclose (f); return; } // write shuffled version if (fwrite(FileName, 1, nStringSize, f) != nStringSize) { fclose(f); return; } fflush(f); uint32 nFileSize2; if (fread (&nFileSize2, sizeof(uint32), 1, f) != 1) { fclose (f); return; } #ifdef NL_BIG_ENDIAN NLMISC_BSWAP32(nFileSize2); #endif uint32 nFilePos; if (fread (&nFilePos, sizeof(uint32), 1, f) != 1) { fclose (f); return; } #ifdef NL_BIG_ENDIAN NLMISC_BSWAP32(nFilePos); #endif } fclose (f); }
//----------------------------------------------- // CSLinkEffectOffensive updateOffensive //----------------------------------------------- bool CSLinkEffectOffensive::updateOffensive(CTimerEvent * event, bool sendReportForXP) { if ( CSLinkEffect::update(event,true) ) return true; CEntityBase * target = CEntityBaseManager::getEntityBasePtr( _TargetRowId ); if ( !target ) { nlwarning("<CSLinkEffectDot update> Invalid target %u",_TargetRowId.getIndex() ); _EndTimer.setRemaining(1, new CEndEffectTimerEvent(this)); return true; } // if target is now protected, cancel the effect CSEffect *effect = target->lookForActiveEffect(EFFECT_FAMILIES::PowerAntiMagicShield); if (effect) { _EndTimer.setRemaining(1, new CEndEffectTimerEvent(this)); return true; } // test target is still valid for a link (can happen in PVP or duel) string errorCode; if ( !PHRASE_UTILITIES::validateSpellTarget(_CreatorRowId, _TargetRowId, ACTNATURE::OFFENSIVE_MAGIC, errorCode, true ) ) { _EndTimer.setRemaining(1, new CEndEffectTimerEvent(this)); return true; } if (_LinkExists) { CEntityBase * caster = CEntityBaseManager::getEntityBasePtr( _CreatorRowId ); if ( !caster ) { nlwarning("<CSLinkEffectDot update> Invalid caster %u",_CreatorRowId.getIndex() ); _EndTimer.setRemaining(1, new CEndEffectTimerEvent(this)); return true; } // test resistance if ( !_FirstResist && !EntitiesNoResist) { uint32 resistValue = 0; if (_Family == EFFECT_FAMILIES::Dot) { CSLinkEffectDot *dot = dynamic_cast<CSLinkEffectDot*> (this); if (dot) { resistValue = target->getMagicResistance(dot->getDamageType()); } } else { resistValue = target->getMagicResistance(_Family); } sint skillValue = 0; if ( caster->getId().getType() == RYZOMID::player ) { CCharacter * pC = (CCharacter *) caster; skillValue = pC->getSkillValue( _Skill ); } else { const CStaticCreatures * form = caster->getForm(); if ( !form ) { nlwarning( "<MAGIC>invalid creature form %s in entity %s", caster->getType().toString().c_str(), caster->getId().toString().c_str() ); _EndTimer.setRemaining(1, new CEndEffectTimerEvent(this)); return true; } skillValue = form->getAttackLevel(); } const CSEffect* debuff = caster->lookForActiveEffect( EFFECT_FAMILIES::DebuffSkillMagic ); if ( debuff ) skillValue -= debuff->getParamValue(); const CSEffect * outPostBuff = caster->lookForActiveEffect( EFFECT_FAMILIES::OutpostMagic ); if ( outPostBuff ) skillValue += outPostBuff->getParamValue(); // cap skill values with brick power if ( (sint32)_Power < skillValue ) skillValue = (sint32)_Power; if ( caster->getId().getType() == RYZOMID::player ) { CCharacter * pC = dynamic_cast<CCharacter *>( caster ); if( pC ) { // boost magic skill for low level chars sint sb = (sint)MagicSkillStartValue.get(); skillValue = max( sb, skillValue ); // add magic boost from consumable skillValue += pC->magicSuccessModifier(); } } // test resistance const uint8 roll = (uint8)RandomGenerator.rand( 99 ); _ResistFactor = CStaticSuccessTable::getSuccessFactor(SUCCESS_TABLE_TYPE::MagicResistLink, skillValue - resistValue, roll); // increase target resistance if (_ResistFactor > 0.0f) { if (_Family == EFFECT_FAMILIES::Dot) { CSLinkEffectDot *dot = dynamic_cast<CSLinkEffectDot*> (this); if (dot) { target->incResistModifier(dot->getDamageType(), _ResistFactor); } } else { target->incResistModifier(_Family,_ResistFactor); } } // delta level for XP gain // opponent must be a creature or an npc to gain xp _Report.DeltaLvl = skillValue - resistValue; if (target->getId().getType() != RYZOMID::player && caster->getId().getType() == RYZOMID::player) { CCreature *creature = dynamic_cast<CCreature*> (target); if (!creature) { nlwarning("Entity %s type is creature but dynamic_cast in CCreature * returns NULL ?!", target->getId().toString().c_str()); _EndTimer.setRemaining(1, new CEndEffectTimerEvent(this)); return true; } CCharacter * pC = dynamic_cast<CCharacter*> (caster); if (!pC) { nlwarning("Entity %s type is player but dynamic_cast in CCharacter * returns NULL ?!", caster->getId().toString().c_str()); _EndTimer.setRemaining(1, new CEndEffectTimerEvent(this)); return true; } const CStaticCreatures* form = creature->getForm(); if (form) _Report.DeltaLvl = pC->getSkillValue(_Skill) - form->getXPLevel(); else sendReportForXP = false; } else sendReportForXP = false; } else { _FirstResist = false; _ResistFactor = 1.0f; } bool end = true; // resist if factor <= 0 if ( _ResistFactor > 0.0f ) { end = false; if ( _ResistFactor > 1.0f ) { _ResistFactor = 1.0f; } // send report for XP _Report.factor = _ResistFactor; if (sendReportForXP) { PROGRESSIONPVE::CCharacterProgressionPVE::getInstance()->actionReport( _Report ); PROGRESSIONPVP::CCharacterProgressionPVP::getInstance()->reportAction(_Report); } } else { PHRASE_UTILITIES::sendSpellResistMessages( _CreatorRowId, _TargetRowId); } ////////////////////////////////////////////////////////////////////////// // TEMPORARY : SEND AGGRO MESSAGE FOR EVERY UPDATE OF OFFENSIVE LINKS ////////////////////////////////////////////////////////////////////////// CAiEventReport report; report.Originator = _CreatorRowId; report.Target = _TargetRowId; report.Type = ACTNATURE::OFFENSIVE_MAGIC; report.AggroAdd = -0.01f; CPhraseManager::getInstance().addAiEventReport(report); ////////////////////////////////////////////////////////////////////////// if (end) { _EndTimer.setRemaining(1, new CEndEffectTimerEvent(this)); return true; } } else { // no link -> no possible resist ? } return false; } // CSLinkEffectOffensive::updateOffensive //
//---------------------------------------------------------------------------- bool CBuildingTest::changeRoom(uint charIndex) { nlassert( charIndex < TestCharacters.size() ); nlassert( TestCharacters[charIndex].InBuilding ); CEntityId id = TestCharacters[charIndex].EId; CCharacter * c = PlayerManager.getChar( id ); nlassert( c ); sint32 cellId = TestCharacters[charIndex].CellId; const IRoomInstance * room = CBuildingManager::getInstance()->getRoomInstanceFromCell( cellId ); if ( !room ) { nlwarning("*** BuildingUnitTest *** cannot get room instance for character %u at cell %d.", charIndex, cellId); return false; } IBuildingPhysical * buildingInst = room->getBuilding(); nlassert( buildingInst ); const uint16 roomIndex = room->getRoomIndex(); vector<IBuildingPhysical::CRoomPhysical> & rooms = buildingInst->_Rooms; nlassert( !rooms.empty() ); if ( rooms.size() == 1 ) return true; // find another room uint16 newRoomIndex; const uint maxLoops = 1000; uint nbLoops = 0; while (1) { nlassert(++nbLoops <= maxLoops); newRoomIndex = (uint16) RandomGenerator.rand( (uint16)rooms.size()-1 ); if (newRoomIndex >= rooms.size()) newRoomIndex = 0; if (newRoomIndex != roomIndex) break; } nlassert( !rooms[newRoomIndex].Cells.empty() ); const sint32 newCellId = rooms[newRoomIndex].Cells[0]; const IRoomInstance * newRoom = CBuildingManager::getInstance()->getRoomInstanceFromCell( newCellId ); if ( !newRoom ) { nlwarning("*** BuildingUnitTest *** cannot get room instance for character %u at cell %d.", charIndex, newCellId); return false; } IBuildingPhysical * newBuildingInst = newRoom->getBuilding(); nlassert( newBuildingInst ); nlassert( newBuildingInst == buildingInst ); // cannot change room if we are in a guild/player building if ( !dynamic_cast<const CRoomInstanceCommon *>( newRoom ) ) return true; if ( !newBuildingInst->addUser( c, newRoomIndex, 0, cellId ) ) { nlwarning("*** BuildingUnitTest *** character %u cannot go from room %hu to room %hu in building %s.", charIndex, roomIndex, newRoomIndex, TestCharacters[charIndex].BuildingName.c_str() ); CBuildingManager::getInstance()->removePlayerFromRoom( c ); return false; } if (Verbose) { nlinfo("*** BuildingUnitTest *** character %u goes from room %hu (cell = %d) to room %hu (cell = %d) in building %s.", charIndex, roomIndex, TestCharacters[charIndex].CellId, newRoomIndex, cellId, TestCharacters[charIndex].BuildingName.c_str() ); } // fake teleport CBuildingManager::getInstance()->removePlayerFromRoom( c ); CMirrorPropValue<TYPE_CELL> mirrorCell( TheDataset, c->getEntityRowId(), DSPropertyCELL ); mirrorCell = cellId; // update character data TestCharacters[charIndex].CellId = cellId; TestCharacters[charIndex].RoomIndex = newRoomIndex; return true; }