void Monster_BladeSpirit::check() { // Our current victim P_CHAR m_currentVictim = World::instance()->findChar( m_currentVictimSer ); if ( !m_currentVictim ) { m_currentVictimSer = INVALID_SERIAL; } if ( m_currentVictim && invalidTarget( m_npc, m_currentVictim ) ) { m_currentVictim = 0; m_currentVictimSer = INVALID_SERIAL; m_npc->fight( 0 ); } if ( nextVictimCheck < Server::instance()->time() ) { // Don't switch if we can hit it... if ( !m_currentVictim || m_currentVictim->dist( m_npc ) > 1 ) { P_CHAR target = findBestTarget( m_npc ); if ( target ) { m_currentVictim = target; m_currentVictimSer = target->serial(); m_npc->fight( target ); } } nextVictimCheck = Server::instance()->time() + 1500; } AbstractAI::check(); }
void cCombat::spawnGuard( P_CHAR pOffender, P_CHAR pCaller, const Coord& pos ) { if ( !pOffender || !pCaller ) return; if ( pOffender->isDead() || pCaller->isDead() ) return; cTerritory* pRegion = pCaller->region(); if ( pRegion == NULL ) return; if ( pRegion->isGuarded() && Config::instance()->guardsActive() ) { QString guardsect = pRegion->getGuardSect(); P_NPC pGuard = ( guardsect.isNull() ? NULL : cNPC::createFromScript( guardsect, pos ) ); if ( !pGuard ) return; // Send guard to surrounding Players pGuard->resend( false ); pGuard->soundEffect( 0x1FE ); pGuard->effect( 0x372A, 0x09, 0x06 ); pGuard->fight( pOffender ); } }
void cTmpEff::Off(P_CHAR pc) { if (!pc) return; switch(this->num) { case 1: pc->priv2 &= 0xFD; break; case 2: pc->fixedlight='\xFF'; break; case 3: pc->chgDex(this->more1); break; case 4: pc->in+=this->more1; break; case 5: pc->st+=this->more1; break; case 6: pc->chgDex(-1 * this->more1);break; case 7: pc->in-=this->more1; break; case 8: pc->st-=this->more1; break; case 11: pc->st-=this->more1; pc->chgDex(-1 * this->more2); pc->in-=this->more3; break; case 12: pc->st+=this->more1; pc->chgDex(this->more2); pc->in+=this->more3; break; } }
// Name: item_bounce3 // Purpose: holds some statements that were COPIED some 50 times // Remarks: temporary functions to revamp the 30 occurences of the 'bouncing bugfix' // History: init Duke, 10.8.2000 / bugfix for bonus stats, Xanathar, 05-aug-2001 static void item_bounce3(const P_ITEM pi) { VALIDATEPI( pi ); pi->setContSerial( pi->getContSerial(true) ); pi->setPosition( pi->getOldPosition() ); pi->layer=pi->oldlayer; P_CHAR pc = pointers::findCharBySerial( pi->getContSerial(true) ); if(pc==NULL) return ; VALIDATEPC( pc ); if ( pi->layer > 0 ) { // Xanathar -- add BONUS STATS given by equipped special items pc->setStrength( pc->getStrength() + pi->st2, true ); //pc->st += pi->st2; pc->dx += pi->dx2; pc->in += pi->in2; // Xanathar -- for poisoned items if (pi->poisoned) { pc->poison += pi->poisoned; if ( pc->poison < 0) pc->poison = 0; } } }
void cScriptManager::reload() { cItemIterator iter_items; cCharIterator iter_chars; P_ITEM pItem; P_CHAR pChar; for ( pItem = iter_items.first(); pItem; pItem = iter_items.next() ) pItem->freezeScriptChain(); for ( pChar = iter_chars.first(); pChar; pChar = iter_chars.next() ) pChar->freezeScriptChain(); // First unload, then reload unload(); // Stop + Restart Python //stopPython(); //startPython( qApp->argc(), qApp->argv() ); PythonEngine::instance()->unload(); PythonEngine::instance()->load(); load(); for ( pItem = iter_items.first(); pItem; pItem = iter_items.next() ) pItem->unfreezeScriptChain(); for ( pChar = iter_chars.first(); pChar; pChar = iter_chars.next() ) pChar->unfreezeScriptChain(); CharBaseDefs::instance()->refreshScripts(); ItemBaseDefs::instance()->refreshScripts(); }
/*! Returns the variant as an int if the variant has type() StringType, CString, IntType, UInt, DoubleType, Bool or KeySequence; or 0 otherwise. If \a ok is non-null, \a *ok is set to TRUE if the value could be converted to an int and FALSE otherwise. \sa asInt() canCast() */ int cVariant::toInt( bool* ok ) const { if ( typ == StringType ) return hex2dec( *( ( QString * ) value.ptr ) ).toInt( ok ); if ( ok ) *ok = canCast( IntType ); if ( typ == IntType ) return value.i; if ( typ == LongType ) return ( int ) value.d; if ( typ == DoubleType ) return ( int ) value.d; if ( typ == BaseCharType ) { P_CHAR pChar = static_cast<P_CHAR>( value.ptr ); return pChar ? pChar->serial() : INVALID_SERIAL; } if ( typ == ItemType ) { P_ITEM pItem = static_cast<P_ITEM>( value.ptr ); return pItem ? pItem->serial() : INVALID_SERIAL; } return 0; }
/*! Returns the variant as a double if the variant has type() StringType, CString, DoubleType, IntType, UInt, or Bool; or 0.0 otherwise. If \a ok is non-null, \a *ok is set to TRUE if the value could be converted to a double and FALSE otherwise. \sa asDouble() */ double cVariant::toDouble( bool* ok ) const { if ( typ == StringType ) return ( ( QString * ) value.ptr )->toDouble( ok ); if ( ok ) *ok = canCast( DoubleType ); if ( typ == DoubleType ) return value.d; if ( typ == IntType ) return ( double ) value.i; if ( typ == LongType ) return ( double ) value.d; if ( typ == BaseCharType ) { P_CHAR pChar = static_cast<P_CHAR>( value.ptr ); return pChar ? ( double ) pChar->serial() : ( double ) INVALID_SERIAL; } if ( typ == ItemType ) { P_ITEM pItem = static_cast<P_ITEM>( value.ptr ); return pItem ? ( double ) pItem->serial() : ( double ) INVALID_SERIAL; } return 0.0; }
// guildrecruit() Let the guild members recruit some player into the guild. // Checks the guild database if "to be recruited" player already in any other guild. // puts a tag with players serial number into the guilds recruit database. void cGuildStone::Recruit(UOXSOCKET s) { if ( currchar[s]->guildstone() == INVALID_SERIAL ) { sysmessage(s,"you are in no guild"); return; } if(buffer[s][11]==0xFF && buffer[s][12]==0xFF && buffer[s][13]==0xFF && buffer[s][14]==0xFF) return; // check if user canceled operation - Morrolan int serial = calcserial(buffer[s][7],buffer[s][8],buffer[s][9],buffer[s][10]); P_CHAR pc = FindCharBySerial( serial ); if(pc != NULL) { if (pc->guildstone() != INVALID_SERIAL) sysmessage(s,"This person is already in a guild."); else { if (pc->isPlayer()) { this->recruit.push_back(pc->serial); } else sysmessage(s,"This is not a player."); } //break; //} for } this->Menu(s,1); return; }
/*! Checks if the specified object is in given range */ bool cUObject::inRange( cUObject* object, quint32 range ) const { if ( !object ) return false; Coord pos = object->pos_; if ( object->isItem() ) { P_ITEM pItem = dynamic_cast<P_ITEM>( object ); if ( pItem ) { P_ITEM pCont = pItem->getOutmostItem(); P_CHAR pEquipped = pItem->getOutmostChar(); if ( pEquipped ) { pos = pEquipped->pos(); } else if ( pCont ) { pos = pCont->pos(); } } } return pos_.distance( pos ) <= range; }
// OKAY (but take another look) // guildresign() : Player gets removed from the guilddatabase, and gets a message. // Offcourse guilddatabase gets checked for members left, if everyone is gone, then vanish // the guildstone. After Guildmaster resigns, the fealty of each remaining member calculates // a new guildmaster, if there is a draw then we'll have no master until they change their minds ;) void GuildResign(int s) { P_CHAR pc = currchar[s]; cGuildStone* pStone = dynamic_cast<cGuildStone*>(FindItemBySerial(pc->guildstone())); if (pStone == NULL) { sysmessage(s, "You are in no guild"); return; } pStone->removeMember( currchar[s] ); sysmessage(s,"You are no longer in that guild."); if ((pStone->ownserial == pc->serial) && (!pStone->member.empty())) { pStone->SetOwnSerial(INVALID_SERIAL); pStone->CalcMaster(); } if (pStone->member.empty()) { Items->DeleItem( pStone ); sysmessage(s,"You have been the last member of that guild so the stone vanishes."); } return; }
// guildtoggleabbreviation() Toggles the settings for showing or not showing the guild title // Informs player about his change void cGuildStone::ToggleAbbreviation(UOXSOCKET s) { P_CHAR pc = currchar[s]; if (!isMember(pc)) { sysmessage(s, "you are not a guild member"); return; } if (this->guildType != cGuildStone::standard) // Check for Order/Chaos { sysmessage(s, "You are in an Order/Chaos guild, you cannot toggle your title."); } else { if (!pc->guildtoggle()) // If set to Off then { pc->setGuildtoggle(true); // Turn it On sysmessage(s, "You toggled your abbreviation on."); // Tell player about the change } else // Otherwise { pc->setGuildtoggle(false); // Turn if Off sysmessage(s, "You toggled your abbreviation off."); // And tell him also } } this->Menu(s, 1); // Send him back to the menu return; }
void cNewMagic::execSpell( P_CHAR pMage, UINT8 spell, UINT8 type, cUORxTarget* target ) { stNewSpell *sInfo = findSpell( spell ); P_PLAYER pp = dynamic_cast<P_PLAYER>(pMage); if( ( ( pp || !pp->isGM() ) && !checkReagents( pMage, spell ) ) || !useMana( pMage, spell ) ) { pMage->setCasting( false ); return; } if( !pp || !pp->isGM() ) useReagents( pMage, spell ); if( !checkSkill( pMage, spell, false ) ) { disturb( pMage, true, -1 ); return; } // Call the Spell Effect for this Spell if( sInfo->script ) sInfo->script->onSpellSuccess( pMage, spell, type, target ); // End Casting pMage->setCasting( false ); }
// TESTED: OKAY (i think so, but ugly -> redo it!) // guildmastercalc(guildnumber) counts all fealty settings of all members of 'guildnumber' and sets // a new guildmaster if there is a draw then there will be no master, til the next check ;) void cGuildStone::CalcMaster() { std::map<unsigned int, unsigned int> votes; // Key is member serial and data #votes unsigned int i; for ( i = 0; i < member.size(); ++i) { P_CHAR pc = FindCharBySerial( member[i] ); votes[pc->guildfealty()]++; } /* struct maxVotes : public binary_function< pair<unsigned int, unsigned int>, pair<unsigned int, unsigned int>, bool> { operator(pair<unsigned int, unsigned int> a, pair<unsigned int, unsigned int> b) { return (a.second < b.second); } };*/ std::map<unsigned int, unsigned int>::iterator it = max_element(votes.begin(), votes.end(), votes.value_comp()); unsigned int currenthighest = it->first; unsigned int currenthighestvotes = it->second; votes.erase( it ); // check for draw; it = max_element(votes.begin(), votes.end(), votes.value_comp()); bool draw = ( it->second == currenthighestvotes ); if (!draw) this->master = currenthighest; }
/*! \brief Check if the player is skilled enough and have requested items \return bool can or can't \param pc the player \param inMenu if write a sysmessage on error \todo Add message if haven't enough item.. */ bool cMakeItem::checkReq( P_CHAR pc, bool inMenu, cRawItem* def ) { if( pc->IsGM() ) return true; if( (skillToCheck!=INVALID) && (pc->skill[skillToCheck]<minskill) ) { if( !inMenu ) pc->sysmsg(TRANSLATE("You're not enough skilled")); return false; } for( int i=0; i<2; ++i ) { cRawItem& raw = reqitems[i]; if( raw.id!=0 ) { bool have = ( def!=NULL )? (def[i].number>=raw.number) : ( pc->CountItems( raw.id, raw.color)>= raw.number ); if( !have ) { if( !inMenu ) pc->sysmsg(TRANSLATE("You've not enough resources")); return false; } } } return true; }
float Action_Defend::postCondition() { /* * Defending has the following postconditions: * - The character isn't attacking us anymore. * - The attacker has died. * - The attacker is not within combat range. * - Health is critical. * * Fuzzy: The nearer we get to the critical health line, * the higher is the chance to end the defend action. */ P_CHAR pAttacker = m_npc->attackTarget(); if( !pAttacker || pAttacker->isDead() ) return 1.0f; UINT8 range = 1; if( m_npc->rightHandItem() && IsBowType( m_npc->rightHandItem()->id() ) ) range = ARCHERY_RANGE; if( !m_npc->inRange( pAttacker, range ) ) return 1.0f; // 1.0 = Full Health, 0.0 = Dead float diff = 1.0 - QMAX(0, (m_npc->maxHitpoints() - m_npc->hitpoints()) / (float)m_npc->maxHitpoints()); if (diff <= m_npc->criticalHealth() / 100.0) { return 1.0; } return 0.0; }
// Tries to equip an item // if that fails it tries to put the item in the users backpack // if *that* fails it puts it at the characters feet // That works for NPCs as well void equipItem( P_CHAR wearer, P_ITEM item ) { tile_st tile = TileCache::instance()->getTile( item->id() ); // User cannot wear the item if ( tile.layer == 0 ) { if ( wearer->objectType() == enPlayer ) { P_PLAYER pp = dynamic_cast<P_PLAYER>( wearer ); if ( pp->socket() ) pp->socket()->sysMessage( tr( "You cannot wear that item." ) ); } item->toBackpack( wearer ); return; } cBaseChar::ItemContainer container = wearer->content(); cBaseChar::ItemContainer::const_iterator it( container.begin() ); for ( ; it != container.end(); ++it ) { P_ITEM equip = *it; // Unequip the item and free the layer that way if ( equip && ( equip->layer() == tile.layer ) ) equip->toBackpack( wearer ); } // *finally* equip the item wearer->addItem( static_cast<cBaseChar::enLayer>( item->layer() ), item ); }
/*! Play the sound effect for a miss. */ void cCombat::playMissedSoundEffect( P_CHAR pChar, UINT16 skill ) { UINT16 id = 0; switch( skill ) { case ARCHERY: id = RandomNum( 0, 1 ) ? 0x233 : 0x238; break; // Wrestling Sounds are creature-dependant case WRESTLING: if( !pChar->isHuman() ) { cCharBaseDef *def = BaseDefManager::instance()->getCharBaseDef( pChar->body() ); if( def != 0 ) id = def->basesound() + RandomNum( 0, 1 ); break; } default: id = RandomNum( 0x238, 0x23a ); break; } if( id != 0 ) pChar->soundEffect( id ); }
void cTmpEff::On(P_CHAR pc) { if (!pc) return; switch(this->num) { case 1: pc->priv2 |= 0x02; break; case 2: pc->fixedlight = SrvParams->worldBrightLevel();break; case 3: pc->chgDex(-1 * this->more1); break; case 4: pc->in-=this->more1; break; case 5: pc->st-=this->more1; break; case 6: pc->chgDex(this->more1); break; case 7: pc->in+=this->more1; break; case 8: pc->st+=this->more1; break; case 11: pc->st+=this->more1; pc->chgDex(this->more2); pc->in+=this->more3; break; case 12: pc->st-=this->more1; pc->chgDex(-1 * this->more2); pc->in-=this->more3; break; } }
int response(UOXSOCKET s, P_CHAR pPlayer, char* SpeechUpr) { char *comm=SpeechUpr; if (strstr( comm, "#EMPTY") && online(currchar[s]) && !pPlayer->dead && pPlayer->isGM()) { // restricted to GMs for now. It's too powerful (Duke, 5.6.2001) target(s, 0, 1, 0, 71, "Select container to empty:"); return 1; } if (!online(DEREF_P_CHAR(pPlayer)) || pPlayer->dead) return 0; P_CHAR pc; cRegion::RegionIterator4Chars ri(pPlayer->pos); for (ri.Begin(); (pc=ri.GetData()) != ri.End(); ri++) { if (pc->isPlayer()) // only npcs will respond automagically, players still have to do that themselves ;) continue; if (pPlayer->dist(pc) > 16) // at least they should be on the screen continue; if (pPlayer->isSameAs(pc)) // not talking to ourselves continue; if (StableSpeech(pc, comm, pPlayer, s)) return 1; if (UnStableSpeech(pc, comm, pPlayer, s)) return 1; if (ShieldSpeech(pc, comm, pPlayer, s)) return 1; if (QuestionSpeech(pc, comm, pPlayer, s)) return 1; if (PackupSpeech(pc, comm, pPlayer, s)) return 1; if (TriggerSpeech(pc, comm, pPlayer, s)) return 1; if (EscortSpeech(pc, comm, pPlayer, s)) return 1; if (BankerSpeech(pc, comm, pPlayer, s)) return 1; if (TrainerSpeech(pc, comm, pPlayer, s)) return 1; if (PetCommand(pc, comm, pPlayer, s)) return 1; if (VendorSpeech(pc, comm, pPlayer, s)) return 1; } return 0; }
/*! \brief Delete an account \author Akron \return true if account is deleted correctly, or false \param name the account name */ bool cAccounts::RemoveAccount(std::string name) { ACCOUNT_LIST_BY_NAME::iterator iter( accbyname.find( name )); ACCOUNT acc; if ( iter==accbyname.end() ) return false; else acc = iter->second; if ( IsOnline(acc) ) { unsigned int r = pointers::findCharBySerial(GetInWorld(acc))->getClient()->toInt(); Network->Disconnect(r); } NxwCharWrapper acc_chars; GetAllChars( acc, acc_chars ); for( acc_chars.rewind(); !acc_chars.isEmpty(); acc_chars++ ) { P_CHAR pc = acc_chars.getChar(); if(ISVALIDPC(pc)) pc->Delete(); } accbyname.erase( name ); acctlist.erase( acc ); SaveAccounts(); return true; }
/*! Sends items which came in range and handles collisions with teleporters or damaging items. */ void handleItems( P_CHAR pChar, const Coord& oldpos ) { P_PLAYER player = dynamic_cast<P_PLAYER>( pChar ); MapItemsIterator iter = MapObjects::instance()->listItemsInCircle( pChar->pos(), VISRANGE ); for ( P_ITEM pItem = iter.first(); pItem; pItem = iter.next() ) { // Check for item collisions here. if ( pChar->pos().x == pItem->pos().x && pChar->pos().y == pItem->pos().y ) { if ( pItem->pos().z >= pChar->pos().z - 15 && pItem->pos().z <= pChar->pos().z + 15 ) { if ( handleItemCollision( pChar, pItem ) ) { break; } } } // If we are a connected player then send new items if ( player && player->socket() ) { UI32 oldDist = oldpos.distance( pItem->pos() ); if ( oldDist >= player->visualRange() ) { // was out of range before and now is in range pItem->update( player->socket() ); } } } }
float Action_FleeAttacker::preCondition() { /* * Fleeing from an attacker has the following preconditions: * - There is a character attacking us. * - The attacking character has not died. * - The attacking character is within flee range. * - The hitpoints are below the critical value. * * Fuzzy: The nearer we get to the critical health, the chance * increases to flee. */ P_CHAR pAttacker = m_npc->attackTarget(); if ( !pAttacker || pAttacker->isDead() || !m_npc->inRange( pAttacker, Config::instance()->pathfindFleeRadius() ) ) return 0.0f; pFleeFromSer = pAttacker->serial(); // 1.0 = Full Health, 0.0 = Dead float diff = 1.0 - wpMax<float>( 0, ( m_npc->maxHitpoints() - m_npc->hitpoints() ) / ( float ) m_npc->maxHitpoints() ); if ( diff <= m_npc->criticalHealth() / 100.0 ) { return 1.0; } return 0.0; }
float Action_FleeAttacker::postCondition() { /* * Fleeing from an attacker has the following postconditions: * - The character isn't attacking us anymore. * - The attacker has died. * - The attacker is not within flee range. * - The hitpoints are restored. * * Fuzzy: The farer we are from the critical health line, * the higher is the chance to end the flee action. */ P_CHAR pAttacker = m_npc->attackTarget(); if ( !pAttacker || pAttacker->isDead() || !m_npc->inRange( pAttacker, Config::instance()->pathfindFleeRadius() ) ) return 1.0f; // 1.0 = Full Health, 0.0 = Dead float diff = 1.0 - wpMax<float>( 0, ( m_npc->maxHitpoints() - m_npc->hitpoints() ) / ( float ) m_npc->maxHitpoints() ); if ( diff <= m_npc->criticalHealth() / 100.0 ) { return 0.0; } return 1.0; }
Coord Coord::losTargetPoint( cUORxTarget* target, unsigned char map ) { SERIAL serial = target->serial(); P_ITEM pItem = World::instance()->findItem( serial ); P_CHAR pChar = World::instance()->findChar( serial ); if ( pItem ) { pItem = pItem->getOutmostItem(); if ( pItem->container() && pItem->container()->isChar() ) { return pItem->container()->pos().losCharPoint(); } else { return pItem->pos().losItemPoint( pItem->id() ); } } else if ( pChar ) { return pChar->pos().losCharPoint(); } else { return Coord( target->x(), target->y(), target->z(), map ); } }
// Remove it from all in-range sockets void cUObject::removeFromView( bool clean ) { // Get Real pos Coord_cl mPos = pos_; if( isItemSerial( serial_ ) ) { P_ITEM pItem = dynamic_cast<P_ITEM>(this); P_ITEM pCont = pItem->getOutmostItem(); if( pCont ) { mPos = pCont->pos(); P_CHAR pOwner = dynamic_cast<P_CHAR>( pCont->container() ); if( pOwner ) mPos = pOwner->pos(); } } cUOTxRemoveObject remove; remove.setSerial(serial_); for (cUOSocket *socket = cNetwork::instance()->first(); socket; socket = cNetwork::instance()->next()) { if (socket->player() != this && (clean || socket->canSee(this))) { socket->send(&remove); } } }
P_CHAR Monster_EnergyVortex::findBestTarget() { int targetAttract = -1; P_CHAR target = 0; if ( !m_npc ) { return target; } // Search for targets in our list of current targets first QList<cFightInfo*> fights = m_npc->fights(); foreach ( cFightInfo* info, fights ) { P_CHAR victim = info->victim(); if ( victim == m_npc ) { victim = info->attacker(); } // We don't already attack the target, right? if ( victim != target ) { // See if it's a target we want unsigned int dist = m_npc->dist(victim); int attract = (victim->intelligence() + victim->skillValue(MAGERY) / 10) / (wpMin<unsigned int>(65535, dist) + 1); if ( attract > targetAttract && validTarget( victim, dist ) ) { target = victim; targetAttract = attract; } } }
void cTempEffects::check() { cTempEffect *tEffect = NULL; if( !teffects.empty() ) tEffect = *teffects.begin(); if( !tEffect) return; while( tEffect && tEffect->expiretime <= uiCurrentTime ) { if( isCharSerial( tEffect->getDest() ) ) { P_CHAR pChar = dynamic_cast< P_CHAR >( FindCharBySerial( tEffect->getDest() ) ); if (pChar) { pChar->removeEffect( tEffect ); } } tEffect->Expire(); std::pop_heap( teffects.begin(), teffects.end(), cTempEffects::ComparePredicate() ); teffects.pop_back(); delete tEffect; if( !teffects.empty() ) tEffect = *teffects.begin(); else break; } }
float Human_Guard_Called_Disappear::preCondition() { P_CHAR pTarget = m_npc->attackTarget(); if ( !pTarget || pTarget->isDead() || pTarget->isInnocent() || pTarget->region() != m_npc->region() ) return 1.0f; return 0.0f; }
void cUOTxSendSkills::fromChar( P_CHAR pChar ) { if( !pChar ) return; for( Q_UINT8 i = 0; i < ALLSKILLS; ++i ) addSkill( i, pChar->skill( i ), pChar->baseSkill( i ), cUOTxSendSkills::Up ); }
// play the get hit animation void cCombat::playGetHitAnimation( P_CHAR pChar ) { if (pChar->isHuman()) { pChar->action(20); } else { pChar->action(10); } }