// 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);
}
Beispiel #3
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;
}
Beispiel #7
0
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