// Handles house commands from friends of the house. // msg must already be capitalized void HouseSpeech( cUOSocket *socket, P_CHAR pPlayer, const QString& msg ) { Q_UNUSED(socket); // Not inside a multi if( pPlayer->multis() == INVALID_SERIAL ) return; P_ITEM pMulti = FindItemBySerial( pPlayer->multis() ); if( !pMulti ) { clConsole.send( tr( "Player %1 [0x%2] has bad multi serial [0x%1]" ).arg( pPlayer->name() ).arg( pPlayer->serial(), 8, 16 ).arg( pPlayer->multis() ) ); pPlayer->setMultis( INVALID_SERIAL ); return; } if ( pMulti && IsHouse( pMulti->id() ) ) { cHouse* pHouse = dynamic_cast< cHouse* >( pMulti ); // Only the owner or a friend of the house can control it if( !( pPlayer->Owns( pHouse ) || pHouse->isFriend( pPlayer ) ) ) return; } else return; // >> LEGACY /*if(msg.contains("I BAN THEE")) { // house ban addid1[s] = pMulti->serial()>>24; addid2[s] = pMulti->serial()>>16; addid3[s] = pMulti->serial()>>8; addid4[s] = pMulti->serial()%256; target(s, 0, 1, 0, 229, "Select person to ban from house."); } else if(msg.contains("REMOVE THYSELF")) { // kick out of house addid1[s] = pMulti->serial()>>24; addid2[s] = pMulti->serial()>>16; addid3[s] = pMulti->serial()>>8; addid4[s] = pMulti->serial()%256; target(s, 0, 1, 0, 228, "Select person to eject from house."); } else if (msg.contains("I WISH TO LOCK THIS DOWN")) { // lock down code AB/LB target(s, 0, 1, 0, 232, "Select item to lock down"); } else if (msg.contains("I WISH TO RELEASE THIS")) { // lock down code AB/LB target(s, 0, 1, 0, 233, "Select item to release"); } else if (msg.contains("I WISH TO SECURE THIS")) { // lock down code AB/LB target(s, 0, 1, 0, 234, "Select item to secure"); }*/ }
void PlVGetgold(int s, cChar* pVendor)//PlayerVendors { unsigned int pay=0, give=pVendor->holdg, t=0; P_CHAR pPlayer = currchar[s]; if (pPlayer->Owns(pVendor)) { if (pVendor->holdg<1) { npctalk(s,pVendor,"I have no gold waiting for you.",0); pVendor->holdg=0; return; } else if(pVendor->holdg <= 65535) { if (pVendor->holdg>9) { pay=(int)(pVendor->holdg*.1); give-=pay; } else { pay=pVendor->holdg; give=0; } pVendor->holdg=0; } else { t=pVendor->holdg-65535; pVendor->holdg=65535; pay=6554; give=58981; } if (give) Items->SpawnItem(s, currchar[s],give,"#",1,0x0E,0xED,0,1,1); sprintf((char*)temp, "Today's purchases total %i gold. I am keeping %i gold for my self. Here is the remaining %i gold. Have a nice day.",pVendor->holdg,pay,give); npctalk(s,pVendor,(char*)temp,0); pVendor->holdg=t; } else npctalk(s,pVendor,"I don't work for you!",0); }
void cCharStuff::CheckAI(unsigned int currenttime, int i) //Lag Fix -- Zippy { int d, onl; unsigned int chance; //unsigned int StartGrid, getcell, increment, a, checkgrid; P_CHAR pc_i = MAKE_CHARREF_LR(i); if (i<0 || i>cmem) return; if (!(nextnpcaitime<=currenttime||(overflow))) return; // in npc.scp add script # for npc`s ai // case - script - case - script - case - script - case - script // 0 - 0 - 4 - 4 - 8 - 8 - 12 - C // 1 - 1 - 5 - 5 - 9 - 9 - 13 - D // 2 - 2 - 6 - 6 - 10 - A - 14 - E // 3 - 3 - 7 - 7 - 11 - B - 15 - F // case - script - case - script // 16 - 10 - 20 - 14 // 17 - 11 - 21 - 15 // 18 - 12 - 22 - 16 // 19 - 13 - 23 - 17 ...this is just a guide...Ripper switch(pc_i->npcaitype) { case 0: // Shopkeepers greet players..Ripper if(server_data.VendorGreet==1 && pc_i->isNpc() && pc_i->shop==1 && pc_i->id1==0x01 && (pc_i->id2==0x90 || pc_i->id2==0x91)) { cRegion::RegionIterator4Chars ri(pc_i->pos); for (ri.Begin(); ri.GetData() != ri.End(); ri++) { P_CHAR pc = ri.GetData(); if (pc != NULL) { onl = online(DEREF_P_CHAR(pc)); d = chardist(i, DEREF_P_CHAR(pc)); if (d > 3) continue; if (pc->isInvul() || pc->isNpc() || pc->dead || !pc->isInnocent() || !onl) continue; sprintf((char*)temp,"Hello %s, Welcome to my shop, How may i help thee?.", pc->name); npctalkall(i,(char*)temp,1); pc_i->antispamtimer=uiCurrentTime+MY_CLOCKS_PER_SEC*30; } } } break; case 1: // good healers if(!pc_i->war) { cRegion::RegionIterator4Chars ri(pc_i->pos); for (ri.Begin(); ri.GetData() != ri.End(); ri++) { P_CHAR pc = ri.GetData(); if (pc != NULL) { onl = online(DEREF_P_CHAR(pc)); d = chardist(i, DEREF_P_CHAR(pc)); if (!pc->dead || d > 3 || pc->isNpc() || !onl) continue; if (pc->isMurderer()) { npctalkall(i, "I will nay give life to a scoundrel like thee!",1); return; } else if (pc->isCriminal()) { npctalkall(i, "I will nay give life to thee for thou art a criminal!",1); return; } else if (pc->isInnocent()) { npcaction(i, 0x10); Targ->NpcResurrectTarget(DEREF_P_CHAR(pc)); staticeffect(DEREF_P_CHAR(pc), 0x37, 0x6A, 0x09, 0x06); switch(RandomNum(0, 4)) { case 0: npctalkall(i, "Thou art dead, but 'tis within my power to resurrect thee. Live!",1); break; case 1: npctalkall(i, "Allow me to resurrect thee ghost. Thy time of true death has not yet come.",1); break; case 2: npctalkall(i, "Perhaps thou shouldst be more careful. Here, I shall resurrect thee.",1); break; case 3: npctalkall(i, "Live again, ghost! Thy time in this world is not yet done.",1); break; case 4: npctalkall(i, "I shall attempt to resurrect thee.",1); break; } } } } } break; case 2 : // Monsters, PK's - (stupid NPCs) if (!pc_i->war) { cRegion::RegionIterator4Chars ri(pc_i->pos); for (ri.Begin(); ri.GetData() != ri.End(); ri++) { P_CHAR pc = ri.GetData(); if (pc != NULL) { onl = online(DEREF_P_CHAR(pc)); d = chardist(i, DEREF_P_CHAR(pc)); chance = RandomNum(1, 100); if (DEREF_P_CHAR(pc) == i) continue; if (d>SrvParms->attack_distance) continue; if (onl &&(pc->isInvul() || pc->isHidden() || pc->dead)) continue; if (pc->isNpc() &&(pc->npcaitype == 2) || pc->npcaitype == 1) continue; if (server_data.monsters_vs_animals == 0 && (strlen(pc->title) > 0 || !onl)) continue; if (server_data.monsters_vs_animals == 1 && chance > server_data.animals_attack_chance) continue; if (pc_i->baseskill[MAGERY]>400) { if (pc_i->hp < (pc_i->st/2)) { npctalkall(i, "In Vas Mani", 0); Magic->NPCHeal(i); } if (pc_i->poisoned) { npctalkall(i, "An Nox", 0); Magic->NPCCure(i); } if (pc->priv2&0x20) { npctalkall(i, "An Ort", 0); Magic->NPCDispel(i, DEREF_P_CHAR(pc)); } } npcattacktarget(i, DEREF_P_CHAR(pc)); return; } } } break; case 3 : //Evil Healers if(!pc_i->war) { cRegion::RegionIterator4Chars ri(pc_i->pos); for (ri.Begin(); ri.GetData() != ri.End(); ri++) { P_CHAR pc = ri.GetData(); if (pc != NULL) { onl = online(DEREF_P_CHAR(pc)); d = chardist(i, DEREF_P_CHAR(pc)); if (!pc->dead || d > 3 || pc->isNpc() || !onl) continue; if (pc->isInnocent()) { npctalkall(i, "I dispise all things good. I shall not give thee another chance!",1); return; } else { npcaction(i, 0x10); Targ->NpcResurrectTarget(DEREF_P_CHAR(pc)); staticeffect(DEREF_P_CHAR(pc), 0x37, 0x09, 0x09, 0x19); //Flamestrike effect switch(RandomNum(0, 4)) { case 0: npctalkall(i, "Fellow minion of Mondain, Live!!",1); break; case 1: npctalkall(i, "Thou has evil flowing through your vains, so I will bring you back to life.",1); break; case 2: npctalkall(i, "If I res thee, promise to raise more hell!.",1); break; case 3: npctalkall(i, "From hell to Britannia, come alive!.",1); break; case 4: npctalkall(i, "Since you are Evil, I will bring you back to consciouness.",1); break; } } } } } break; case 4 : // Guards if (!pc_i->war // guard isnt busy && pc_i->inGuardedArea()) // this region is guarded { cRegion::RegionIterator4Chars ri(pc_i->pos); for (ri.Begin(); ri.GetData() != ri.End(); ri++) { P_CHAR pc = ri.GetData(); if (pc != NULL) { onl = online(DEREF_P_CHAR(pc)); d = chardist(i, DEREF_P_CHAR(pc)); if (d > 10 || pc->isInvul() || pc->dead || !onl) continue; npcattacktarget(i, DEREF_P_CHAR(pc)); npctalkall(i, "Thou shalt regret thine actions, swine!",1); // ANTISPAM !!! LB } } } break; case 5: // npc beggars if (!pc_i->war) { cRegion::RegionIterator4Chars ri(pc_i->pos); for (ri.Begin(); ri.GetData() != ri.End(); ri++) { P_CHAR pc = ri.GetData(); if (pc != NULL) { onl = online(DEREF_P_CHAR(pc)); d = chardist(i, DEREF_P_CHAR(pc)); if (d > 3 || pc->isInvul() || pc->isNpc() || pc->dead || !onl || !pc->isInnocent()) continue; int beg= RandomNum (0,2); { switch (beg) { case 0: npctalkall(i,"Could thou spare a few coins?",1); pc_i->antispamtimer=uiCurrentTime+MY_CLOCKS_PER_SEC*30; break; case 1: npctalkall(i,"Hey buddy can you spare some gold?",1); pc_i->antispamtimer=uiCurrentTime+MY_CLOCKS_PER_SEC*30; break; case 2: npctalkall(i,"I have a family to feed, think of the children.",1); pc_i->antispamtimer=uiCurrentTime+MY_CLOCKS_PER_SEC*30; break; default: break; } } } } } break; case 6: break; // Ripper- chaos guards. case 7: break; // Ripper- order guards. case 8: break; //morrolan - old banker case 9 : // in world guards, they dont teleport out...Ripper if (!pc_i->war // guard isnt busy && pc_i->inGuardedArea()) // this region is guarded { // this bracket just to keep compiler happy cRegion::RegionIterator4Chars ri(pc_i->pos); for (ri.Begin(); ri.GetData() != ri.End(); ri++) { P_CHAR pc = ri.GetData(); if (pc != NULL) { onl = online(DEREF_P_CHAR(pc)); d = chardist(i, DEREF_P_CHAR(pc)); if (i==DEREF_P_CHAR(pc) || d > 3 || pc->isInvul() || pc->dead || !onl) continue; if ( pc->isPlayer() && pc->crimflag > 0 ) { sprintf((char*)temp,"You better watch your step %s, I am watching thee!!", pc->name); npctalkall(i,(char*)temp,1); pc_i->antispamtimer=uiCurrentTime+MY_CLOCKS_PER_SEC*30; } else if ( pc->isPlayer() && pc->isInnocent() && !pc->dead ) { sprintf((char*)temp,"%s is an upstanding citizen, I will protect thee in %s.", pc->name, region[pc->region].name); npctalkall(i,(char*)temp,1); pc_i->antispamtimer=uiCurrentTime+MY_CLOCKS_PER_SEC*30; } else if ( d<=10 && ( (pc->isNpc() && (pc->npcaitype==2)) // evil npc || (pc->isPlayer() && !(pc->isInnocent()) && !(pc->isCriminal())) // a player, not grey or blue || (pc->attackfirst==1))) // any agressor { pc_i->pos.x=pc->pos.x; //Ripper..guards teleport to enemies. pc_i->pos.y=pc->pos.y; pc_i->pos.z=pc->pos.z; soundeffect2(i, 0x01, 0xFE); // crashfix, LB staticeffect(i, 0x37, 0x2A, 0x09, 0x06); npcattacktarget(i, DEREF_P_CHAR(pc)); npctalkall(i, "Thou shalt regret thine actions, swine!",1); // ANTISPAM !!! LB return; } } } } break; case 10: // Tamed Dragons ..not white wyrm..Ripper // so regular dragons attack reds on sight while tamed. if(pc_i->isNpc() && pc_i->tamed) { cRegion::RegionIterator4Chars ri(pc_i->pos); for (ri.Begin(); ri.GetData() != ri.End(); ri++) { P_CHAR pc = ri.GetData(); if (pc != NULL) { onl = online(DEREF_P_CHAR(pc)); d = chardist(i, DEREF_P_CHAR(pc)); if(d > 10 || pc->isPlayer() || pc->npcaitype!=2) continue; npcattacktarget(i,DEREF_P_CHAR(pc)); return; } } } break; case 11 : // add NPCAI B in scripts to make them attack reds. (Ripper) if (!pc_i->war) { cRegion::RegionIterator4Chars ri(pc_i->pos); for (ri.Begin(); ri.GetData() != ri.End(); ri++) { P_CHAR pc = ri.GetData(); if (pc != NULL) { onl = online(DEREF_P_CHAR(pc)); d = chardist(i, DEREF_P_CHAR(pc)); if (d > 10 || pc->isInvul() || pc->dead || !onl) continue; if (pc->npcaitype!=2 || !pc->isCriminal() || !pc->isMurderer()) continue; npcattacktarget(i, DEREF_P_CHAR(pc)); } } } break; case 17: break; //Zippy Player Vendors. case 30: // why is this the same as case 50???..Ripper if (!pc_i->war) { cRegion::RegionIterator4Chars ri(pc_i->pos); for (ri.Begin(); ri.GetData() != ri.End(); ri++) { P_CHAR pc = ri.GetData(); if (pc != NULL) { onl = online(DEREF_P_CHAR(pc)); d = chardist(i, DEREF_P_CHAR(pc)); if (d > 10 || pc->isInvul() || pc->dead || pc->npcaitype!=2 || !onl) continue; npcattacktarget(i, DEREF_P_CHAR(pc)); return; } } } break; case 32: // Pets Guarding..Ripper if(pc_i->isNpc() && pc_i->tamed) { cRegion::RegionIterator4Chars ri(pc_i->pos); for (ri.Begin(); ri.GetData() != ri.End(); ri++) { P_CHAR pc = ri.GetData(); if (pc != NULL) { onl = online(DEREF_P_CHAR(pc)); d = chardist(i, DEREF_P_CHAR(pc)); if (d > 10 || pc->isNpc() || pc->dead || !pc->guarded || !onl) continue; if(pc->Owns(pc_i)) { npcattacktarget(i,pc->attacker); return; } } } } break; case 50://EV/BS if (!pc_i->war) { cRegion::RegionIterator4Chars ri(pc_i->pos); for (ri.Begin(); ri.GetData() != ri.End(); ri++) { P_CHAR pc = ri.GetData(); if (pc != NULL) { onl = online(DEREF_P_CHAR(pc)); d = chardist(i, DEREF_P_CHAR(pc)); if (d > 10 || pc->isInvul() || pc->dead || !onl) continue; npcattacktarget(i, DEREF_P_CHAR(pc)); return; } } } break; // Case 60-70 is Skyfires new AI case 96: case 60: //Skyfire - Dragon AI if (pc_i->war) { cRegion::RegionIterator4Chars ri(pc_i->pos); for (ri.Begin(); ri.GetData() != ri.End(); ri++) { P_CHAR pc = ri.GetData(); if (pc != NULL) { onl = online(DEREF_P_CHAR(pc)); d = chardist(i, DEREF_P_CHAR(pc)); if (pc->isNpc() || pc->dead || !onl) continue; if (d > 4 && pc_i->attacker==DEREF_P_CHAR(pc)) { if (Combat->GetBowType(DEREF_P_CHAR(pc))!=0) { pc_i->pos.x=pc->pos.x; pc_i->pos.y=pc->pos.y; pc_i->pos.z=pc->pos.z; pc_i->dir=pc->dir; teleport(i); npctalkall(i,"Foolish Mortal!",0); } } else { switch(RandomNum(0, 4)) { case 0: Magic->NPCEBoltTarget(i,DEREF_P_CHAR(pc)); break; case 1: Magic->NPCFlameStrikeTarget(i,DEREF_P_CHAR(pc)); break; case 2: Magic->ParalyzeSpell(i,DEREF_P_CHAR(pc)); break; case 3: Magic->NPCLightningTarget(i,DEREF_P_CHAR(pc)); break; case 4: Magic->ParalyzeSpell(i,DEREF_P_CHAR(pc)); break; } } } if (pc_i->hp<(pc_i->st/2)) Magic->NPCHeal(i); if (pc_i->poisoned) Magic->NPCCure(i); if (pc->priv2&0x20) Magic->NPCDispel(i,DEREF_P_CHAR(pc)); npcattacktarget(i, DEREF_P_CHAR(pc)); return; } } else { if (pc_i->hp<(pc_i->st/2)) Magic->NPCHeal(i); if (pc_i->poisoned) Magic->NPCCure(i); } break; default: clConsole.send("ERROR: cCharStuff::CheckAI-> Error npc %i (%x %x %x %x) has invalid AI type %i\n",i,pc_i->ser1,pc_i->ser2,pc_i->ser3,pc_i->ser4,pc_i->npcaitype); //Morrolan return; }// switch }// void checknpcai
// New Class implementation void cDragItems::grabItem( P_CLIENT client ) { // Get our character P_CHAR pChar = client->player(); if( pChar == NULL ) return; // Fetch the grab information SERIAL iSerial = LongFromCharPtr( &buffer[ client->socket() ][ 1 ] ); UI16 amount = ShortFromCharPtr( &buffer[ client->socket() ][ 5 ] ); P_ITEM pItem = FindItemBySerial( iSerial ); if( !pItem ) return; // Are we already dragging an item ? // Bounce it and reject the move // (Logged out while dragging an item) if( client->dragging() ) { bounceItem( client, client->dragging() ); bounceItem( client, pItem, true ); return; } // Do we really want to let him break his meditation // When he picks up an item ? // Maybe a meditation check here ?!? pChar->disturbMed( client->socket() ); // Meditation P_CHAR itemOwner = GetPackOwner( pItem, 64 ); // Try to pick something out of another characters posessions if( itemOwner && ( itemOwner != pChar ) && ( !pChar->Owns( itemOwner ) ) ) { client->sysMessage( QString( "You have to steal the %1 out of %2's posessions." ).arg( pItem->getName() ).arg( itemOwner->name.c_str() ) ); bounceItem( client, pItem, true ); return; } // Check if the user can grab the item if( !pChar->canPickUp( pItem ) ) { client->sysMessage( "You cannot pick that up." ); bounceItem( client, pItem, true ); return; } // The user can't see the item // Basically thats impossible as the client should deny moving the item // if it's not in line of sight but to prevent exploits if( !line_of_sight( client->socket(), pChar->pos, pItem->pos, TREES_BUSHES|WALLS_CHIMNEYS|DOORS|ROOFING_SLANTED|FLOORS_FLAT_ROOFING|LAVA_WATER ) ) { client->sysMessage( "You can't see the item." ); bounceItem( client, pItem, true ); return; } P_ITEM outmostCont = GetOutmostCont( pItem, 64 ); // If it's a trade-window, reset the ack-status if( outmostCont && ( outmostCont->contserial == pChar->serial ) && ( outmostCont->layer() == 0 ) && ( outmostCont->id() == 0x1E5E ) ) { // Get the other sides tradewindow P_ITEM tradeWindow = FindItemBySerial( calcserial( outmostCont->moreb1(), outmostCont->moreb2(), outmostCont->moreb3(), outmostCont->moreb4() ) ); // If one of the trade-windows has the ack-status reset it if( tradeWindow && ( tradeWindow->morez || outmostCont->morez ) ) { tradeWindow->morez = 0; outmostCont->morez = 0; sendtradestatus( tradeWindow, outmostCont ); } } // If the top-most container ( thats important ) is a corpse // and looting is a crime, flag the character criminal. if( outmostCont && outmostCont->corpse() ) { // For each item we take out we loose carma // if the corpse is innocent and not in our guild bool sameGuild = ( GuildCompare( pChar, FindCharBySerial( outmostCont->ownserial ) ) != 0 ); if( ( outmostCont->more2 == 1 ) && !pChar->Owns( outmostCont ) && !sameGuild ) { pChar->karma -= 5; criminal( pChar ); client->sysMessage( "You lost some karma." ); } } // Check if the item is too heavy //if( !pc_currchar->isGMorCounselor() ) //{ //} << Deactivated (DarkStorm) // ==== Grabbing the Item is allowed here ==== // Remove eventual item-bonusses if we're unequipping something if( pItem->layer() > 0 ) { P_CHAR wearer = FindCharBySerial( pItem->contserial ); if( wearer ) wearer->removeItemBonus( pItem ); } // Send the user a pickup sound if we're picking it up // From a container/paperdoll if( !pItem->isInWorld() ) soundeffect( client->socket(), 0x00, 0x57 ); // If we're picking up a specific amount of what we got // Take that into account if( pItem->amount() > 1 ) { UI32 pickedAmount = min( amount, pItem->amount() ); // We only have to split if we're not taking it all if( pickedAmount != pItem->amount() ) { P_ITEM splitItem = new cItem( *pItem ); // Create a new item to pick that up splitItem->SetSerial( cItemsManager::getInstance()->getUnusedSerial() ); splitItem->setAmount( pItem->amount() - pickedAmount ); splitItem->setContSerial( pItem->contserial ); splitItem->SetOwnSerial( pItem->ownserial ); splitItem->SetSpawnSerial( pItem->spawnserial ); // He needs to see the new item RefreshItem( splitItem ); // If we're taking something out of a spawn-region it's spawning "flag" is removed isn't it? pItem->SetSpawnSerial( INVALID_SERIAL ); pItem->setAmount( pickedAmount ); } } pItem->setContSerial( pChar->serial ); pItem->SetMultiSerial( INVALID_SERIAL ); pItem->setLayer( 0x1E ); // It's in the equipment of another character if( itemOwner && ( itemOwner != pChar ) ) { itemOwner->weight -= pItem->getWeight(); statwindow( calcSocketFromChar( itemOwner ), itemOwner ); } // If the item is in the bank or any sell-container it's NOT counted as char-weight bool inBank = ( outmostCont && ( outmostCont->contserial == pChar->serial ) && ( outmostCont->layer() >= 0x1A ) ); // Add the weight if: // - Picked from ground // - Picked out of another character // - Picked out of our bank or any other non-visible container if( ( itemOwner != pChar ) || !inBank ) { pChar->weight += pItem->getWeight(); statwindow( client->socket(), pChar ); } }
void cDragItems::dropOnItem( P_CLIENT client, P_ITEM pItem, P_ITEM pCont, const Coord_cl &dropPos ) { P_CHAR pChar = client->player(); if( pItem->isMulti() ) { client->sysMessage( "You cannot put houses in containers" ); bounceItem( client, pItem ); return; } // If the target belongs to another character // It needs to be our vendor or else it's denied P_CHAR packOwner = GetPackOwner( pCont ); if( ( packOwner != NULL ) && ( packOwner != pChar ) ) { // For each item someone puts into there // He needs to do a snoop-check if( pChar->canSnoop() ) { if( !Skills->CheckSkill( pChar, SNOOPING, 0, 1000 ) ) { client->sysMessage( QString( "You fail to put that into %1's pack" ).arg( packOwner->name.c_str() ) ); bounceItem( client, pItem ); return; } } if( !packOwner->isNpc() || ( packOwner->npcaitype() != 17 ) || !pChar->Owns( packOwner ) ) { client->sysMessage( "You cannot put that into the belongings of another player" ); bounceItem( client, pItem ); return; } } // If we put the item into a trade-window // Reset the trade-status for both players if( pCont->layer() == 0 && pCont->id() == 0x1E5E && pChar->Wears( pCont ) ) { // Trade window??? P_ITEM tradeWindow = FindItemBySerial( calcserial( pCont->moreb1(), pCont->moreb2(), pCont->moreb3(), pCont->moreb4() ) ); // If it *IS* a trade-window, replace the status if( tradeWindow && ( pCont->morez || tradeWindow->morez ) ) { tradeWindow->morez = 0; pCont->morez = 0; sendtradestatus( tradeWindow, pCont ); } } if( !pChar->canPickUp( pItem ) ) { bounceItem( client, pItem ); return; } // Trash can if( pCont->type()==87 ) { Items->DeleItem( pItem ); client->sysMessage( "As you let go of the item it disappears." ); return; } // Spell Book if( pCont->type() == 9 ) { UI08 spellId = Magic->calcSpellId( pItem->id() ); if( spellId < 0 ) { client->sysMessage( "You can only put scrolls into a spellbook" ); bounceItem( client, pItem ); return; } if( Magic->hasSpell( pCont, spellId ) ) { client->sysMessage( "That spellbook already contains this spell" ); bounceItem( client, pItem ); return; } } // We drop something on the belongings of one of our playervendors if( ( packOwner != NULL ) && ( packOwner->npcaitype() == 17 ) && pChar->Owns( packOwner ) ) { client->sysMessage( "You drop something into your playervendor" ); bounceItem( client, pItem ); return; } // Playervendors (chest equipped by the vendor - opened to the client) /*if( !( pCont->pileable() && pItem->pileable() && pCont->id() == pItem->id() || ( pCont->type() != 1 && pCont->type() != 9 ) ) ) { P_CHAR pc_j = GetPackOwner(pCont); if (pc_j != NULL) { if (pc_j->npcaitype() == 17 && pc_j->isNpc() && pChar->Owns(pc_j)) { pChar->inputitem = pItem->serial; pChar->inputmode = cChar::enPricing; sysmessage(s, "Set a price for this item."); } } */ // We may also drop into *any* locked chest // So we can have post-boxes ;o) // Spellbooks are containers for us as well if( pCont->type() == 9 || pCont->type() == 1 || pCont->type() == 8 || pCont->type() == 63 || pCont->type() == 65 || pCont->type() == 66 ) { pItem->setContSerial( pCont->serial ); pItem->setLayer( 0 ); // Remove it from our drag-layer // Huh ? - Make that random will you! pItem->pos = dropPos; SndRemoveitem( pItem->serial ); RefreshItem( pItem ); // Dropped on another Container/in another Container soundeffect2( pChar, 0x57 ); return; } // Item matching needs to be extended !!! at least Color! (for certain types) else if ( pCont->isPileable() && pItem->isPileable() && ( pCont->id() == pItem->id() ) ) { if( pCont->amount() + pItem->amount() <= 65535 ) { pCont->setAmount( pCont->amount() + pItem->amount() ); Items->DeleItem( pItem ); RefreshItem( pCont ); // Need to update the amount return; } // We have to *keep* our current item else { pCont->setAmount( 65535 ); // Max out the amount RefreshItem( pCont ); // The delta between 65535 and pCont->amount() sub our Amount is the // new amount pItem->setAmount( pItem->amount() - ( 65535 - pCont->amount() ) ); } } // We dropped the item NOT on a container // And were *un*able to stack it (!) // >> Set it to the location of the item we dropped it on and stack it up by 1 pItem->moveTo( pCont->pos ); pItem->pos.z++; // Increase z by 1 pItem->pos.y++; // To get it visualized do that with y as well pItem->setLayer( 0 ); pItem->setContSerial( pCont->contserial ); RefreshItem( pItem ); // This needs to be checked // It annoyingly shows the spellbook // whenever you add a scroll if( pCont->type() == 9 ) Magic->openSpellBook( pChar, pCont ); // Glowing Objects moved between chars if( pItem->glow != INVALID_SERIAL ) { pChar->removeHalo( pItem ); if( packOwner != NULL ) { packOwner->addHalo(pItem); packOwner->glowHalo(pItem); } } }
void cDragItems::dropOnChar( P_CLIENT client, P_ITEM pItem, P_CHAR pOtherChar ) { // Three possibilities: // If we're dropping it on ourself: packintobackpack // If we're dropping it on some other player: trade-window // If we're dropping it on some NPC: checkBehaviours // If not handeled: Equip the item if the NPC is owned by us P_CHAR pChar = client->player(); // Dropped on ourself if( pChar == pOtherChar ) { pItem->setLayer( 0 ); pItem->setContSerial( INVALID_SERIAL ); pItem->toBackpack( pChar ); return; } // Are we in range of our target if( !inrange1p( pChar, pOtherChar ) ) { client->sysMessage( "You are too far away from that character." ); bounceItem( client, pItem ); return; } // Can wee see our target if( !line_of_sight( client->socket(), pChar->pos, pOtherChar->pos, TREES_BUSHES|WALLS_CHIMNEYS|DOORS|ROOFING_SLANTED|FLOORS_FLAT_ROOFING|LAVA_WATER ) ) { client->sysMessage( "You can't see this character" ); bounceItem( client, pItem ); return; } // Open a secure trading window if( !pOtherChar->isNpc() && online( pOtherChar ) ) { // Check if we're already trading, // if not create a new window vector< SERIAL > equipment = contsp.getData( pChar->serial ); P_ITEM tradeWindow = NULL; for( UI16 i = 0; i < equipment.size(); i++ ) { P_ITEM pEquip = FindItemBySerial( equipment[ i ] ); // Is it a trade-window ? if( ( pEquip->layer() == 0 ) && ( pEquip->id() == 0x1E5E ) ) { P_ITEM tradeWindow = FindItemBySerial( calcserial( pEquip->moreb1(), pEquip->moreb2(), pEquip->moreb3(), pEquip->moreb4() ) ); if( tradeWindow && ( tradeWindow->contserial == pOtherChar->serial ) ) { tradeWindow = pEquip; break; } } } if( !tradeWindow ) tradeWindow = Trade->tradestart( client->socket(), pOtherChar ); pItem->setContSerial( tradeWindow->serial); pItem->pos.x = rand() % 60; pItem->pos.y = rand() % 60; pItem->pos.z = 9; pItem->setLayer( 0 ); SndRemoveitem( pItem->serial ); RefreshItem( pItem ); return; } // For our hirelings we have a special function if( pChar->Owns( pOtherChar ) ) { dropOnPet( client, pItem, pOtherChar ); return; } // Dropping based on AI Type switch( pOtherChar->npcaitype() ) { case 4: dropOnGuard( client, pItem, pOtherChar ); break; case 5: dropOnBeggar( client, pItem, pOtherChar ); break; case 8: dropOnBanker( client, pItem, pOtherChar ); break; case 19: dropOnBroker( client, pItem, pOtherChar ); break; }; // Try to train - works for any NPC if( pOtherChar->cantrain() ) if( pChar->trainer() == pOtherChar->serial ) dropOnTrainer( client, pItem, pOtherChar ); else pOtherChar->talk( "You need to tell me what you want to learn first" ); bounceItem( client, pItem ); return; }
void cCharStuff::CheckAI(unsigned int currenttime, P_CHAR pc_i) // Lag Fix -- Zippy { int d; unsigned int chance; if ( pc_i == NULL ) return; if (!(nextnpcaitime <= currenttime || (overflow))) return; // in npc.scp add script # for npc`s ai // case - script - case - script - case - script - case - script // 0 - 0 - 4 - 4 - 8 - 8 - 12 - C // 1 - 1 - 5 - 5 - 9 - 9 - 13 - D // 2 - 2 - 6 - 6 - 10 - A - 14 - E // 3 - 3 - 7 - 7 - 11 - B - 15 - F // case - script - case - script // 16 - 10 - 20 - 14 // 17 - 11 - 21 - 15 // 18 - 12 - 22 - 16 // 19 - 13 - 23 - 17 ...this is just a guide...Ripper switch (pc_i->npcaitype) { case 0: // Shopkeepers greet players..Ripper if (SrvParams->shopInvul() == 1 && pc_i->isNpc() && pc_i->shop && pc_i->isHuman()) { pc_i->makeInvulnerable(); }else{ pc_i->makeVulnerable(); } if (SrvParams->vendorGreet() == 1 && pc_i->isNpc() && pc_i->shop && pc_i->isHuman()) { cRegion::RegionIterator4Chars ri(pc_i->pos); for (ri.Begin(); !ri.atEnd(); ri++) { P_CHAR pc = ri.GetData(); if (pc != NULL) { d = chardist( pc_i, pc ); if (d > 3) continue; if (pc->isNpc() || !online(pc)) continue; if (pc->isInvul() || pc->dead || !pc->isInnocent()) continue; sprintf((char*)temp, "Hello %s, Welcome to my shop, How may i help thee?.", pc->name.c_str()); npctalkall(pc_i, (char*)temp, 1); pc_i->antispamtimer = uiCurrentTime + MY_CLOCKS_PER_SEC*30; } } } break; case 1: // good healers if (!pc_i->war) { cRegion::RegionIterator4Chars ri(pc_i->pos); for (ri.Begin(); !ri.atEnd(); ri++) { P_CHAR pc = ri.GetData(); if (pc != NULL) { d = chardist( pc_i, pc ); if (d > 3) continue; if (pc->isNpc() || !online(pc)) continue; if (!pc->dead) continue; if (pc->isMurderer()) { npctalkall(pc_i, "I will nay give life to a scoundrel like thee!", 1); return; } else if (pc->isCriminal()) { npctalkall(pc_i, "I will nay give life to thee for thou art a criminal!", 1); return; } else if (pc->isInnocent()) { npcaction(pc_i, 0x10); Targ->NpcResurrectTarget(pc); staticeffect(pc, 0x37, 0x6A, 0x09, 0x06); switch (RandomNum(0, 4)) { case 0: npctalkall(pc_i, "Thou art dead, but 'tis within my power to resurrect thee. Live!", 1); break; case 1: npctalkall(pc_i, "Allow me to resurrect thee ghost. Thy time of true death has not yet come.", 1); break; case 2: npctalkall(pc_i, "Perhaps thou shouldst be more careful. Here, I shall resurrect thee.", 1); break; case 3: npctalkall(pc_i, "Live again, ghost! Thy time in this world is not yet done.", 1); break; case 4: npctalkall(pc_i, "I shall attempt to resurrect thee.", 1); break; } } } } } break; case 2 : // Monsters, PK's - (stupid NPCs) if (!pc_i->war) { // Get the one with the least distance! P_CHAR Victim = NULL; UI32 minDist; cRegion::RegionIterator4Chars ri(pc_i->pos); for (ri.Begin(); !ri.atEnd(); ri++) { P_CHAR pc = ri.GetData(); if( pc == NULL ) continue; d = chardist( pc_i, pc ); chance = RandomNum(1, 100); if( ( !pc->isNpc() ) && ( !online( pc ) ) ) continue; if ( d > SrvParams->attack_distance() ) continue; if ( pc->isInvul() || pc->isHidden() || pc->dead ) continue; if ( pc->isNpc() && ( pc->npcaitype == 2 || pc->npcaitype == 1 ) ) continue; if ( SrvParams->monsters_vs_animals() == 0 && ( pc->title.size() <= 0 && !pc->isHuman() ) ) continue; if ( SrvParams->monsters_vs_animals() == 1 && chance > SrvParams->animals_attack_chance() ) continue; // If the distance is below the minimal distance we found if( ( Victim == NULL ) || ( minDist > d ) ) { Victim = pc; minDist = d; } } if (pc_i->baseskill[MAGERY]>400) { if (pc_i->hp <(pc_i->st/2)) { npctalkall(pc_i, "In Vas Mani", 0); Magic->NPCHeal(pc_i); } else if (pc_i->poisoned) { npctalkall(pc_i, "An Nox", 0); Magic->NPCCure(pc_i); } else if ( Victim && Victim->priv2&0x20 ) { npctalkall(pc_i, "An Ort", 0); Magic->NPCDispel(pc_i, Victim); } } // We found a victim if( Victim != NULL ) npcattacktarget(pc_i, Victim); return; } break; case 3 : // Evil Healers if (!pc_i->war) { cRegion::RegionIterator4Chars ri(pc_i->pos); for (ri.Begin(); !ri.atEnd(); ri++) { P_CHAR pc = ri.GetData(); if (pc != NULL) { d = chardist( pc_i, pc ); if (d > 3) continue; if (pc->isNpc() || !online(pc)) continue; if (!pc->dead) continue; if (pc->isInnocent()) { npctalkall(pc_i, "I dispise all things good. I shall not give thee another chance!", 1); return; } else { npcaction(pc_i, 0x10); Targ->NpcResurrectTarget(pc); staticeffect(pc, 0x37, 0x09, 0x09, 0x19); // Flamestrike effect switch (RandomNum(0, 4)) { case 0: npctalkall(pc_i, "Fellow minion of Mondain, Live!!", 1); break; case 1: npctalkall(pc_i, "Thou has evil flowing through your vains, so I will bring you back to life.", 1); break; case 2: npctalkall(pc_i, "If I res thee, promise to raise more hell!.", 1); break; case 3: npctalkall(pc_i, "From hell to Britannia, come alive!.", 1); break; case 4: npctalkall(pc_i, "Since you are Evil, I will bring you back to consciouness.", 1); break; } } } } } break; case 4 : // Teleporting Guards if (!pc_i->war // guard isnt busy && pc_i->inGuardedArea()) // this region is guarded { // this bracket just to keep compiler happy if (SrvParams->guardsInvul() == 1) { pc_i->makeInvulnerable(); }else{ pc_i->makeVulnerable(); } P_CHAR Victim = NULL; UI32 minDist; cRegion::RegionIterator4Chars ri(pc_i->pos); for (ri.Begin(); !ri.atEnd(); ri++) { P_CHAR pc = ri.GetData(); if (pc != NULL) { d = chardist( pc_i, pc); if( ( !pc->isNpc() ) && ( !online( pc ) ) ) continue; if (pc_i == pc || d > SrvParams->attack_distance() || pc->isInvul() || pc->dead) continue; if (!pc->inGuardedArea()) continue; // If the distance is below the minimal distance we found if( ( Victim == NULL ) || ( minDist > d ) ) { Victim = pc; minDist = d; } if (pc->isPlayer() && pc->crimflag > 0 && d <= 3) { sprintf((char*)temp, "You better watch your step %s, I am watching thee!!", pc->name.c_str()); npctalkall(pc_i, (char*)temp, 1); pc_i->antispamtimer = uiCurrentTime + MY_CLOCKS_PER_SEC*30; } else if (pc->isPlayer() && pc->isInnocent() && d <= 3) { sprintf((char*)temp, "%s is an upstanding citizen, I will protect thee in %s.", pc->name.c_str(), region[pc->region].name); npctalkall(pc_i, (char*)temp, 1); pc_i->antispamtimer = uiCurrentTime + MY_CLOCKS_PER_SEC*30; } else if (d <= SrvParams->attack_distance() &&( (pc->isNpc() &&(pc->npcaitype == 2)) // evil npc ||(pc->isPlayer() && pc->isMurderer() && !(pc->isInnocent()) || pc->isCriminal())) // a player,is murderer & not grey or blue ||(pc->attackfirst == 1)) // any agressor { pc_i->pos.x = pc->pos.x; // Ripper..guards teleport to enemies. pc_i->pos.y = pc->pos.y; pc_i->pos.z = pc->pos.z; soundeffect2(pc_i, 0x01FE); // crashfix, LB staticeffect(pc_i, 0x37, 0x2A, 0x09, 0x06); // We found a victim if( Victim != NULL ) npcattacktarget(pc_i, Victim); npctalkall(pc_i, "Thou shalt regret thine actions, swine!", 1); // ANTISPAM !!! LB return; } } } } break; case 5: // npc beggars if (!pc_i->war) { cRegion::RegionIterator4Chars ri(pc_i->pos); for (ri.Begin(); !ri.atEnd(); ri++) { P_CHAR pc = ri.GetData(); if (pc != NULL) { d = chardist( pc_i, pc ); if (d > 3) continue; if (pc->isNpc() || !online(pc)) continue; if (pc->isInvul() || pc->dead || !pc->isInnocent()) continue; int beg= RandomNum(0, 2); { switch (beg) { case 0: npctalkall(pc_i, "Could thou spare a few coins?", 1); pc_i->antispamtimer = uiCurrentTime + MY_CLOCKS_PER_SEC*30; break; case 1: npctalkall(pc_i, "Hey buddy can you spare some gold?", 1); pc_i->antispamtimer = uiCurrentTime + MY_CLOCKS_PER_SEC*30; break; case 2: npctalkall(pc_i, "I have a family to feed, think of the children.", 1); pc_i->antispamtimer = uiCurrentTime + MY_CLOCKS_PER_SEC*30; break; default: break; } } } } } break; case 6: break; // Ripper- chaos guards. case 7: break; // Ripper- order guards. case 8: break; // morrolan - old banker case 9 : // in world guards, they dont teleport out...Ripper if (!pc_i->war // guard isnt busy && pc_i->inGuardedArea()) // this region is guarded { // this bracket just to keep compiler happy if (SrvParams->guardsInvul() == 1) { pc_i->makeInvulnerable(); }else{ pc_i->makeVulnerable(); } P_CHAR Victim = NULL; UI32 minDist; cRegion::RegionIterator4Chars ri(pc_i->pos); for (ri.Begin(); !ri.atEnd(); ri++) { P_CHAR pc = ri.GetData(); if (pc != NULL) { d = chardist( pc_i, pc); if( ( !pc->isNpc() ) && ( !online( pc ) ) ) continue; if (pc_i == pc || d > SrvParams->attack_distance() || pc->isInvul() || pc->dead) continue; if (!pc->inGuardedArea()) continue; // If the distance is below the minimal distance we found if( ( Victim == NULL ) || ( minDist > d ) ) { Victim = pc; minDist = d; } if (pc->isPlayer() && pc->crimflag > 0 && d <= 3) { sprintf((char*)temp, "You better watch your step %s, I am watching thee!!", pc->name.c_str()); npctalkall(pc_i, (char*)temp, 1); pc_i->antispamtimer = uiCurrentTime + MY_CLOCKS_PER_SEC*30; } else if (pc->isPlayer() && pc->isInnocent() && d <= 3) { sprintf((char*)temp, "%s is an upstanding citizen, I will protect thee in %s.", pc->name.c_str(), region[pc->region].name); npctalkall(pc_i, (char*)temp, 1); pc_i->antispamtimer = uiCurrentTime + MY_CLOCKS_PER_SEC*30; } else if (d <= SrvParams->attack_distance() &&( (pc->isNpc() &&(pc->npcaitype == 2)) // evil npc ||(pc->isPlayer() && pc->isMurderer() && !(pc->isInnocent()) || pc->isCriminal())) // a player,is murderer & not grey or blue ||(pc->attackfirst == 1)) // any agressor { pc_i->pos.x = pc->pos.x; // Ripper..guards teleport to enemies. pc_i->pos.y = pc->pos.y; pc_i->pos.z = pc->pos.z; soundeffect2(pc_i, 0x01FE); // crashfix, LB staticeffect(pc_i, 0x37, 0x2A, 0x09, 0x06); // We found a victim if( Victim != NULL ) npcattacktarget(pc_i, Victim); npctalkall(pc_i, "Thou shalt regret thine actions, swine!", 1); // ANTISPAM !!! LB return; } } } } break; case 10: // Tamed Dragons ..not white wyrm..Ripper // so regular dragons attack reds on sight while tamed. if (pc_i->isNpc() && pc_i->tamed) { cRegion::RegionIterator4Chars ri(pc_i->pos); for (ri.Begin(); !ri.atEnd(); ri++) { P_CHAR pc = ri.GetData(); if (pc != NULL) { d = chardist( pc_i, pc ); if (d > SrvParams->attack_distance()) continue; if (pc->isPlayer()) continue; if (pc->isNpc() && pc->npcaitype != 2) continue; npcattacktarget(pc_i, pc); return; } } } break; case 11 : // add NPCAI B in scripts to make them attack reds. (Ripper) if (!pc_i->war) { cRegion::RegionIterator4Chars ri(pc_i->pos); for (ri.Begin(); !ri.atEnd(); ri++) { P_CHAR pc = ri.GetData(); if (pc != NULL) { d = chardist( pc_i, pc ); if (d > SrvParams->attack_distance()) continue; if( ( !pc->isNpc() ) && ( !online( pc ) ) ) continue; if (pc->isInvul() || pc->dead) continue; if (!(pc->npcaitype == 2 || pc->isMurderer())) continue; npcattacktarget(pc_i, pc); } } } break; case 17: break; // Zippy Player Vendors. case 18: // Ripper.. Escort speech. if (!pc_i->war && pc_i->questType == ESCORTQUEST) { cRegion::RegionIterator4Chars ri(pc_i->pos); for (ri.Begin(); !ri.atEnd(); ri++) { P_CHAR pc = ri.GetData(); if (pc != NULL) { d = chardist(pc_i, pc); if (d > 10) continue; if( ( pc->isNpc() ) && ( !online( pc ) ) ) continue; if (pc->dead) continue; sprintf((char*)temp,"I am waiting for my escort to %s, Will you take me?", region[pc_i->questDestRegion].name); npctalkall(pc_i,(char*)temp,1); pc_i->antispamtimer=uiCurrentTime+MY_CLOCKS_PER_SEC*30; return; } } } break; case 19: break; // real estate broker...Ripper case 32: // Pets Guarding..Ripper if (pc_i->isNpc() && pc_i->tamed) { cRegion::RegionIterator4Chars ri(pc_i->pos); for (ri.Begin(); !ri.atEnd(); ri++) { P_CHAR pc = ri.GetData(); if (pc != NULL) { d = chardist(pc_i, pc); if (d > SrvParams->attack_distance()) continue; if( ( !pc->isNpc() ) && ( !online( pc ) ) ) continue; if (pc->dead) continue; if (!pc->guarded) continue; if (pc->Owns(pc_i)) { P_CHAR pc_target = FindCharBySerial(pc->attacker); npcattacktarget(pc_i, pc_target); return; } } } } break; case 30:// no idea? case 50:// EV/BS if (!pc_i->war) { cRegion::RegionIterator4Chars ri(pc_i->pos); for (ri.Begin(); !ri.atEnd(); ri++) { P_CHAR pc = ri.GetData(); if (pc != NULL) { d = chardist(pc_i, pc); if (d > SrvParams->attack_distance()) continue; if( ( !pc->isNpc() ) && ( !online( pc ) ) ) continue; if (pc->isInvul() || pc->dead) continue; npcattacktarget(pc_i, pc); return; } } } break; case 96: case 60: // Skyfire - Dragon AI DragonAI->DoAI(pc_i, currenttime); break; default: clConsole.send("ERROR: cCharStuff::CheckAI-> Error npc (%8x) has invalid AI type %i\n", pc_i->serial, pc_i->npcaitype); // Morrolan return; }// switch }// void checknpcai