//s: char#
void cCombat::SpawnGuard(P_CHAR pc_offender, P_CHAR pc_caller, int x, int y, signed char z)
{
	int t;
//	if (i < 0 || i >= cmem || s < 0 || s >= cmem)
//		return;
	
//	P_CHAR pc_offender = MAKE_CHARREF_LR(s);
//	P_CHAR pc_caller   = MAKE_CHARREF_LR(i);
	if ( pc_offender == NULL || pc_caller == NULL)
		return;
	
	if (!(pc_caller->inGuardedArea() || pc_offender->inGuardedArea()))
		return;
	
	if (pc_offender->dead || pc_caller->dead)
		return; // AntiChrist
	
	if (SrvParams->guardsActive() && !pc_offender->isInvul())
	{
        t = region[pc_caller->region].guardnum[(rand()%10)];
		P_CHAR pc_guard = Npcs->AddNPCxyz(calcSocketFromChar(pc_offender), t, 0, x, y, z);
		if ( pc_guard == NULL ) return;
		
		pc_guard->npcaitype = 4; // CITY GUARD, LB, bugfix, was 0x40 -> not existing
		pc_guard->setAttackFirst();
		pc_guard->attacker = pc_offender->serial;
		pc_guard->targ = pc_offender->serial;
		pc_guard->npcWander = 2;  // set wander mode Tauriel
		npcToggleCombat(pc_guard);
		pc_guard->setNextMoveTime();
		pc_guard->summontimer =(getNormalizedTime() +(MY_CLOCKS_PER_SEC*25));    
		
		soundeffect2(pc_guard, 0x01FE);  // Tauriel 1-9-99 changed to stop crashing used to call soundeffect (expeted socket)
		staticeffect(pc_guard, 0x37, 0x2A, 0x09, 0x06);
		
		updatechar(pc_guard);
		switch (RandomNum(0,1))
		{
		case 0:		npctalkall(pc_guard, "Thou shalt regret thine actions, swine!", 1);	break;
		case 1:		npctalkall(pc_guard, "Death to all Evil!", 1);							break;
		}
	}
}
void cCombat::ItemCastSpell(UOXSOCKET s, P_CHAR pc, P_ITEM pi)//S=Socket c=Char # Target i=Item //Itemid
{
	if(!pi) return;
	P_CHAR pc_currchar = currchar[s];
	unsigned short int spellnum=((pi->morex*8)-8)+pi->morey;
	unsigned short int tempmana=pc_currchar->mn;//Save their mana so we can give it back.
	unsigned short int tempmage=pc_currchar->skill[MAGERY];//Easier than writing new functions for all these spells


	if(pi->type!=15) return;
	
	if(pi->morez<=0) return;
	
	switch(spellnum)
	{
	case 1:  Magic->ClumsySpell(pc_currchar,pc); break; //LB
	case 3:  Magic->FeebleMindSpell(pc_currchar,pc); break; //LB
	case 5:	 Magic->MagicArrow(pc_currchar,pc);		break; // lB
	case 8:  Magic->WeakenSpell(pc_currchar,pc); break; //LB
	case 18: Magic->FireballSpell(pc_currchar,pc); break; //LB
	case 22: Magic->HarmSpell(pc_currchar,pc); break; //LB
	case 27: Magic->CurseSpell(pc_currchar,pc); break; //LB
	case 30: Magic->LightningSpell(pc_currchar,pc); break; //lb
	case 37: Magic->MindBlastSpell(pc_currchar,pc); break;
	case 38: Magic->ParalyzeSpell(pc_currchar,pc);	break; //lb
	case 42: Magic->EnergyBoltSpell(pc_currchar,pc); break;
	case 43: Magic->ExplosionSpell(pc_currchar,pc); break;
	case 51: Magic->FlameStrikeSpell(pc_currchar,pc); break;
	default:
		staticeffect(pc_currchar, 0x37, 0x35, 0, 30);
		soundeffect2(pc_currchar, 0x005C);
		break;
	}
	pc_currchar->mn+=tempmana;
	pc_currchar->skill[MAGERY]=tempmage;
	if(pc_currchar->in<pc_currchar->mn) pc_currchar->mn=pc_currchar->in;//Shouldn't happen, but just in case;
	updatestats(pc_currchar, 1);
	
	pi->morez--;
	if(pi->morez==0)//JUST lost it's charge....
		sysmessage(s, tr("This item is out of charges."));
}
Exemple #3
0
void deadattack (NXWSOCKET  s, CHARACTER i)
{
	CHARACTER cc = currchar[s];
	P_CHAR pc = MAKE_CHAR_REF( cc );
	VALIDATEPC( pc );
	P_CHAR pc_other = MAKE_CHAR_REF( i );
	VALIDATEPC( pc_other );

	if(pc_other->npc)
	{
		if(pc_other->npcaitype==NPCAI_HEALER)
		{
			if( pc->IsInnocent() )
			{
				if ( pc->distFrom( pc_other ) <= 3 )
				{//let's resurrect him!
					pc_other->playAction(0x10);
					pc->resurrect();
					staticeffect(cc, 0x37, 0x6A, 0x09, 0x06);
					switch(RandomNum(0, 4))
					{
					case 0: pc_other->talkAll( TRANSLATE("Thou art dead, but 'tis within my power to resurrect thee.  Live!"),0); break;
					case 1: pc_other->talkAll( TRANSLATE("Allow me to resurrect thee ghost.  Thy time of true death has not yet come."),0); break;
					case 2: pc_other->talkAll( TRANSLATE("Perhaps thou shouldst be more careful.  Here, I shall resurrect thee."),0); break;
					case 3: pc_other->talkAll( TRANSLATE("Live again, ghost!  Thy time in this world is not yet done."),0); break;
					case 4: pc_other->talkAll( TRANSLATE("I shall attempt to resurrect thee."),0); break;
					}
				}
				else
				{//if dist>3
					pc_other->talkAll( TRANSLATE("Come nearer, ghost, and i'll give you life!"),1);
				}
			}
			else
			{//if a bad guy
				pc_other->talkAll( TRANSLATE("I will not give life to a scoundrel like thee!"),1);
			}
		}
		else if( pc_other->npcaitype == NPCAI_EVILHEALER )
		{
			if( pc->IsMurderer())
			{
				if ( pc->distFrom( pc_other ) <=3 )
				{//let's resurrect him!
					pc_other->playAction(0x10);
					pc->resurrect();
					staticeffect(cc, 0x37, 0x09, 0x09, 0x19); //Flamestrike effect
					switch(rand()%5)
					{
						case 0: pc_other->talkAll( TRANSLATE("Fellow minion of Mondain, Live!!"),0); break;
						case 1: pc_other->talkAll( TRANSLATE("Thou has evil flowing through your vains, so I will bring you back to life."),0); break;
						case 2: pc_other->talkAll( TRANSLATE("If I res thee, promise to raise more hell!."),0); break;
						case 3: pc_other->talkAll( TRANSLATE("From hell to Britannia, come alive!."),0); break;
						case 4: pc_other->talkAll( TRANSLATE("Since you are Evil, I will bring you back to consciouness."),0); break;
					}
				}
				else
				{//if dist >3
					pc_other->talkAll( TRANSLATE("Come nearer, evil soul, and i'll give you life!"),1);
				}
			}
			else
			{//if player is a good guy
				pc_other->talkAll( TRANSLATE("I dispise all things good. I shall not give thee another chance!"),1);
			}
		}
		else
		{
			sysmessage(s,TRANSLATE("You are dead and cannot do that."));
		}//npcaitype check
	}
	else
	{//if this not a npc but a player
		if(SrvParms->persecute)
		{//start persecute stuff - AntiChrist
			pc->targserial = pc_other->getSerial32();
			Skills::Persecute(s);
		}
		else
		{
			sysmessage(s,TRANSLATE("You are dead and cannot do that."));
		}
	}//if npc

}
void dump_item(P_CLIENT ps, PKGx08 *pp) // Item is dropped on ground or a character
{
//	tile_st tile;
	UOXSOCKET s=ps->GetSocket();
	CHARACTER cc=ps->GetCurrChar();
	P_CHAR pc_currchar = MAKE_CHARREF_LR(cc);
	
	P_ITEM pi=FindItemBySerial(pp->Iserial);
	if (!pi)
	{
		LogErrorVar("client sent bad itemserial %d",pp->Iserial);
		return;
	}

	Weight->NewCalc(DEREF_P_CHAR(pc_currchar));
	statwindow(s,DEREF_P_CHAR(pc_currchar));
	pi->flags.isBeeingDragged=false;
	
	//Ripper...so order/chaos shields disappear when on ground.
	if( pi->id1 == 0x1B && ( pi->id2 == 0xC3 || pi->id2 == 0xC4 ) )
	{
		soundeffect2(DEREF_P_CHAR(pc_currchar), 0x01, 0xFE);
		staticeffect(DEREF_P_CHAR(pc_currchar), 0x37, 0x2A, 0x09, 0x06);
		Items->DeleItem( pi );
		return;
	}
	
	//test UOP blocking Tauriel 1-12-99
	if (!pi->isInWorld())
	{
		item_bounce6(ps,pi);
		return;
	}
	
	if (!pc_currchar->canPickUp(pi))
	{
		item_bounce6(ps,pi);
		return;
	}
	
	if (buffer[s][5]!=(unsigned char)'\xFF')
	{
		pi->MoveTo(pp->TxLoc,pp->TyLoc,pp->TzLoc);
		pi->SetContSerial(-1);
		
		if (pi->glow)
		{
			pc_currchar->removeHalo(pi);
			pc_currchar->glowHalo(pi);
		}		
		SndRemoveitem(pi->serial);
		RefreshItem(pi);
	}
	else
	{
		ItemDroppedOnChar(ps, pp, pi);
		
		Weight->NewCalc(DEREF_P_CHAR(pc_currchar));  // Ison 2-20-99
		statwindow(s,DEREF_P_CHAR(pc_currchar));
		itemsfx(s, pi->id());	// Dupois - see itemsfx() for details// Added Oct 09, 1998
		
		//Boats !
		if (pc_currchar->multis>0) //How can they put an item in a multi if they aren't in one themselves Cut lag by not checking everytime something is put down
		{
			P_ITEM pi_multi = FindItemBySerial( pc_currchar->multis );
			if (pi_multi != NULL)
			{
				pi_multi = findmulti(pi->pos);
				if (pi_multi != NULL)
					pi->SetMultiSerial(pi_multi->serial);
			}
		}
		//End Bots
	}
}
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
void advancementobjects(int s, int x, int allways)
{
	char sect[512];
	unsigned long loopexit=0;

	P_CHAR pc_s = MAKE_CHARREF_LR(s);

	int pos;
	if ((pc_s->advobj==0)||(allways==1))
	{
		staticeffect(s, 0x37, 0x3A, 0, 15);
		soundeffect2(s, 0x01, 0xE9);
		pc_s->advobj=x;
		openscript("advance.scp");
		sprintf(sect, "ADVANCEMENT %i", x);
		if (!i_scripts[advance_script]->find(sect))
		{
			closescript();
			clConsole.send("ADVANCEMENT OBJECT: Script section not found. Aborting.\n");
			pc_s->advobj=0;
			return;
		}
		else			
			do
			{
				read2();
				if (script1[0]!='}')
				{
					if ((!(strcmp("STR",(char*)script1)))||(!(strcmp("STRENGTH",(char*)script1))))
					{
						pc_s->st= getstatskillvalue((char*)script2);
						pc_s->st2 = pc_s->st;
					}
					if ((!(strcmp("DEX",(char*)script1)))||(!(strcmp("DEXTERITY",(char*)script1))))
					{
						pc_s->setDex(getstatskillvalue((char*)script2));
					}
					if ((!(strcmp("INT",(char*)script1)))||(!(strcmp("INTELLIGENCE",(char*)script1))))
					{
						pc_s->in= getstatskillvalue((char*)script2);
						pc_s->in2 = pc_s->in;
					}
					if ((!(strcmp("ALCHEMY",(char*)script1)))||(!(strcmp("SKILL0",(char*)script1)))) pc_s->baseskill[ALCHEMY] = getstatskillvalue((char*)script2);
					if ((!(strcmp("ANATOMY",(char*)script1)))||(!(strcmp("SKILL1",(char*)script1)))) pc_s->baseskill[ANATOMY] = getstatskillvalue((char*)script2);
					if ((!(strcmp("ANIMALLORE",(char*)script1)))||(!(strcmp("SKILL2",(char*)script1)))) pc_s->baseskill[ANIMALLORE] = getstatskillvalue((char*)script2);
					if ((!(strcmp("ITEMID",(char*)script1)))||(!(strcmp("SKILL3",(char*)script1)))) pc_s->baseskill[ITEMID] = getstatskillvalue((char*)script2);
					if ((!(strcmp("ARMSLORE",(char*)script1)))||(!(strcmp("SKILL4",(char*)script1)))) pc_s->baseskill[ARMSLORE] = getstatskillvalue((char*)script2);
					if ((!(strcmp("PARRYING",(char*)script1)))||(!(strcmp("SKILL5",(char*)script1)))) pc_s->baseskill[PARRYING] = getstatskillvalue((char*)script2);
					if ((!(strcmp("BEGGING",(char*)script1)))||(!(strcmp("SKILL6",(char*)script1)))) pc_s->baseskill[BEGGING] = getstatskillvalue((char*)script2);
					if ((!(strcmp("BLACKSMITHING",(char*)script1)))||(!(strcmp("SKILL7",(char*)script1)))) pc_s->baseskill[BLACKSMITHING] = getstatskillvalue((char*)script2);
					if ((!(strcmp("BOWCRAFT",(char*)script1)))||(!(strcmp("SKILL8",(char*)script1)))) pc_s->baseskill[BOWCRAFT] = getstatskillvalue((char*)script2);
					if ((!(strcmp("PEACEMAKING",(char*)script1)))||(!(strcmp("SKILL9",(char*)script1)))) pc_s->baseskill[PEACEMAKING] = getstatskillvalue((char*)script2);
					if ((!(strcmp("CAMPING",(char*)script1)))||(!(strcmp("SKILL10",(char*)script1)))) pc_s->baseskill[CAMPING] = getstatskillvalue((char*)script2);
					if ((!(strcmp("CARPENTRY",(char*)script1)))||(!(strcmp("SKILL11",(char*)script1)))) pc_s->baseskill[CARPENTRY] = getstatskillvalue((char*)script2);
					if ((!(strcmp("CARTOGRAPHY",(char*)script1)))||(!(strcmp("SKILL12",(char*)script1)))) pc_s->baseskill[CARTOGRAPHY] = getstatskillvalue((char*)script2);
					if ((!(strcmp("COOKING",(char*)script1)))||(!(strcmp("SKILL13",(char*)script1)))) pc_s->baseskill[COOKING] = getstatskillvalue((char*)script2);
					if ((!(strcmp("DETECTINGHIDDEN",(char*)script1)))||(!(strcmp("SKILL14",(char*)script1)))) pc_s->baseskill[DETECTINGHIDDEN] = getstatskillvalue((char*)script2);
					if ((!(strcmp("ENTICEMENT",(char*)script1)))||(!(strcmp("SKILL15",(char*)script1)))) pc_s->baseskill[ENTICEMENT] = getstatskillvalue((char*)script2);
					if ((!(strcmp("EVALUATINGINTEL",(char*)script1)))||(!(strcmp("SKILL16",(char*)script1)))) pc_s->baseskill[EVALUATINGINTEL] = getstatskillvalue((char*)script2);
					if ((!(strcmp("HEALING",(char*)script1)))||(!(strcmp("SKILL17",(char*)script1)))) pc_s->baseskill[HEALING] = getstatskillvalue((char*)script2);
					if ((!(strcmp("FISHING",(char*)script1)))||(!(strcmp("SKILL18",(char*)script1)))) pc_s->baseskill[FISHING] = getstatskillvalue((char*)script2);
					if ((!(strcmp("FORENSICS",(char*)script1)))||(!(strcmp("SKILL19",(char*)script1)))) pc_s->baseskill[FORENSICS] = getstatskillvalue((char*)script2);
					if ((!(strcmp("HERDING",(char*)script1)))||(!(strcmp("SKILL20",(char*)script1)))) pc_s->baseskill[HERDING] = getstatskillvalue((char*)script2);
					if ((!(strcmp("HIDING",(char*)script1)))||(!(strcmp("SKILL21",(char*)script1)))) pc_s->baseskill[HIDING] = getstatskillvalue((char*)script2);
					if ((!(strcmp("PROVOCATION",(char*)script1)))||(!(strcmp("SKILL22",(char*)script1)))) pc_s->baseskill[PROVOCATION] = getstatskillvalue((char*)script2);
					if ((!(strcmp("INSCRIPTION",(char*)script1)))||(!(strcmp("SKILL23",(char*)script1)))) pc_s->baseskill[INSCRIPTION] = getstatskillvalue((char*)script2);
					if ((!(strcmp("LOCKPICKING",(char*)script1)))||(!(strcmp("SKILL24",(char*)script1)))) pc_s->baseskill[LOCKPICKING] = getstatskillvalue((char*)script2);
					if ((!(strcmp("MAGERY",(char*)script1)))||(!(strcmp("SKILL25",(char*)script1)))) pc_s->baseskill[MAGERY] = getstatskillvalue((char*)script2);
					if ((!(strcmp("MAGICRESISTANCE",(char*)script1)))||(!(strcmp("RESIST",(char*)script1)))||(!(strcmp("SKILL26",(char*)script1)))) pc_s->baseskill[MAGICRESISTANCE] = getstatskillvalue((char*)script2);
					if ((!(strcmp("TACTICS",(char*)script1)))||(!(strcmp("SKILL27",(char*)script1)))) pc_s->baseskill[TACTICS] = getstatskillvalue((char*)script2);
					if ((!(strcmp("SNOOPING",(char*)script1)))||(!(strcmp("SKILL28",(char*)script1)))) pc_s->baseskill[SNOOPING] = getstatskillvalue((char*)script2);
					if ((!(strcmp("MUSICIANSHIP",(char*)script1)))||(!(strcmp("SKILL29",(char*)script1)))) pc_s->baseskill[MUSICIANSHIP] = getstatskillvalue((char*)script2);
					if ((!(strcmp("POISONING",(char*)script1)))||(!(strcmp("SKILL30",(char*)script1)))) pc_s->baseskill[POISONING] = getstatskillvalue((char*)script2);
					if ((!(strcmp("ARCHERY",(char*)script1)))||(!(strcmp("SKILL31",(char*)script1)))) pc_s->baseskill[ARCHERY] = getstatskillvalue((char*)script2);
					if ((!(strcmp("SPIRITSPEAK",(char*)script1)))||(!(strcmp("SKILL32",(char*)script1)))) pc_s->baseskill[SPIRITSPEAK] = getstatskillvalue((char*)script2);
					if ((!(strcmp("STEALING",(char*)script1)))||(!(strcmp("SKILL33",(char*)script1)))) pc_s->baseskill[STEALING] = getstatskillvalue((char*)script2);
					if ((!(strcmp("TAILORING",(char*)script1)))||(!(strcmp("SKILL34",(char*)script1)))) pc_s->baseskill[TAILORING] = getstatskillvalue((char*)script2);
					if ((!(strcmp("TAMING",(char*)script1)))||(!(strcmp("SKILL35",(char*)script1)))) pc_s->baseskill[TAMING] = getstatskillvalue((char*)script2);
					if ((!(strcmp("TASTEID",(char*)script1)))||(!(strcmp("SKILL36",(char*)script1)))) pc_s->baseskill[TASTEID] = getstatskillvalue((char*)script2);
					if ((!(strcmp("TINKERING",(char*)script1)))||(!(strcmp("SKILL37",(char*)script1)))) pc_s->baseskill[TINKERING] = getstatskillvalue((char*)script2);
					if ((!(strcmp("TRACKING",(char*)script1)))||(!(strcmp("SKILL38",(char*)script1)))) pc_s->baseskill[TRACKING] = getstatskillvalue((char*)script2);
					if ((!(strcmp("VETERINARY",(char*)script1)))||(!(strcmp("SKILL39",(char*)script1)))) pc_s->baseskill[VETERINARY] = getstatskillvalue((char*)script2);
					if ((!(strcmp("SWORDSMANSHIP",(char*)script1)))||(!(strcmp("SKILL40",(char*)script1)))) pc_s->baseskill[SWORDSMANSHIP] = getstatskillvalue((char*)script2);
					if ((!(strcmp("MACEFIGHTING",(char*)script1)))||(!(strcmp("SKILL41",(char*)script1)))) pc_s->baseskill[MACEFIGHTING] = getstatskillvalue((char*)script2);
					if ((!(strcmp("FENCING",(char*)script1)))||(!(strcmp("SKILL42",(char*)script1)))) pc_s->baseskill[FENCING] = getstatskillvalue((char*)script2);
					if ((!(strcmp("WRESTLING",(char*)script1)))||(!(strcmp("SKILL43",(char*)script1)))) pc_s->baseskill[WRESTLING] = getstatskillvalue((char*)script2);
					if ((!(strcmp("LUMBERJACKING",(char*)script1)))||(!(strcmp("SKILL44",(char*)script1)))) pc_s->baseskill[LUMBERJACKING] = getstatskillvalue((char*)script2);
					if ((!(strcmp("MINING",(char*)script1)))||(!(strcmp("SKILL45",(char*)script1)))) pc_s->baseskill[MINING] = getstatskillvalue((char*)script2);

					// lb, new skills
					if ((!(strcmp("MEDITATION",(char*)script1)))||(!(strcmp("SKILL46",(char*)script1)))) pc_s->baseskill[MEDITATION] = getstatskillvalue((char*)script2);
					if ((!(strcmp("STEALTH",(char*)script1)))||(!(strcmp("SKILL47",(char*)script1)))) pc_s->baseskill[STEALTH] = getstatskillvalue((char*)script2);
					if ((!(strcmp("REMOVETRAPS",(char*)script1)))||(!(strcmp("SKILL48",(char*)script1)))) pc_s->baseskill[REMOVETRAPS] = getstatskillvalue((char*)script2);

					if ((!(strcmp("DYEHAIR",(char*)script1))))
					{
						unsigned int ci;
						vector<SERIAL> vecContainer = contsp.getData(pc_s->serial);
						P_ITEM pi_hair = NULL;
						for (ci = 0; ci < vecContainer.size(); ci++)
						{
							P_ITEM pi_temp = FindItemBySerial(vecContainer[ci]);
							if (pi_temp != NULL)
								if (pi_temp->layer == 0x0B)
								{
									pi_hair = pi_temp;
									break;
								}
						}
						if (pi_hair != NULL)
						{
							x=hex2num(script2);
							pi_hair->color1=x>>8;
							pi_hair->color2=x%256;
							RefreshItem(pi_hair);//AntiChrist
							teleport(DEREF_P_CHAR(pc_s));
						}
					}

					if ((!(strcmp("DYEBEARD",(char*)script1))))
					{
						int ci;
						P_ITEM pi_beard = NULL;
						vector<SERIAL> vecContainer = contsp.getData(pc_s->serial);
						for (ci = 0; ci < vecContainer.size();ci++)
						{
							P_ITEM pi_temp = FindItemBySerial(vecContainer[ci]);
							if (pi_temp != NULL)
								if (pi_temp->layer == 0x10)
								{
									pi_beard = pi_temp;
									break;
								}
						}
						if (pi_beard != NULL)
						{
							x=hex2num(script2);
							pi_beard->color1=x>>8;
							pi_beard->color2=x%256;
							RefreshItem(pi_beard);//AntiChrist
							teleport(DEREF_P_CHAR(pc_s));
						}
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
Exemple #8
0
void dump_item(NXWCLIENT ps, PKGx08 *pp) // Item is dropped on ground or a character
{
	if (ps == NULL) return;

	tile_st tile;
	NXWSOCKET  s=ps->toInt();

	P_CHAR pc=ps->currChar();
	VALIDATEPC(pc);

	P_ITEM pi=pointers::findItemBySerial(pp->Iserial);


	if (!ISVALIDPI(pi))
	{
		LogError("client sent bad itemserial %d",pp->Iserial);
		return;
	}

	if ( isCharSerial(pi->getContSerial()) && pi->getContSerial() != pc->getSerial32() ) {
		P_CHAR pc_i = pointers::findCharBySerial(pi->getContSerial());
		if (ISVALIDPC(pc_i))
			pc_i->sysmsg("Warning, backpack disappearing bug located!");

		if (ps->isDragging()) {
                        ps->resetDragging();
                        UpdateStatusWindow(s,pi);
                }
		pi->setContSerial( pi->getContSerial(true) );
                pi->setPosition( pi->getOldPosition() );
                pi->layer = pi->oldlayer;
                pi->Refresh();
	}

	if (pi->magic == 2) { //Luxor -- not movable objects
		if (ps->isDragging()) {
                        ps->resetDragging();
                        UpdateStatusWindow(s,pi);
                }
		pi->setContSerial( pi->getContSerial(true) );
		pi->MoveTo( pi->getOldPosition() );
		pi->layer = pi->oldlayer;
		pi->Refresh();
		return;
	}




    if(pi!=NULL)
	{
		weights::NewCalc(pc);
		statwindow(pc,pc);
	}


	//Ripper...so order/chaos shields disappear when on ground.
	if( pi->getId()==0x1BC3 || pi->getId()==0x1BC4 )
	{
		pc->playSFX( 0x01FE);
		staticeffect(DEREF_P_CHAR(pc), 0x37, 0x2A, 0x09, 0x06);
		pi->Delete();
		return;
	}


	//test UOP blocking Tauriel 1-12-99
	if (!pi->isInWorld())
	{
		item_bounce6(ps,pi);
		return;
	}




	data::seekTile(pi->getId(), tile);
	if (!pc->IsGM() && ((pi->magic==2 || (tile.weight==255 && pi->magic!=1))&&!pc->canAllMove()) ||
		( (pi->magic==3 || pi->magic==4) && !(pi->getOwnerSerial32()==pc->getSerial32())))
	{
		item_bounce6(ps,pi);
		return;
	}

	if (buffer[s][5]!=(unsigned char)'\xFF')
	{


		if (pi->amxevents[EVENT_IDROPINLAND]!=NULL) 
		{
			g_bByPass = false;
			pi->MoveTo(pp->TxLoc,pp->TyLoc,pp->TzLoc);
			pi->amxevents[EVENT_IDROPINLAND]->Call( pi->getSerial32(), pc->getSerial32() );
			if (g_bByPass) {
				pi->Refresh();
				return;
			}
		}

		/*
		//<Luxor>
		g_bByPass = false;
		pi->runAmxEvent( EVENT_IDROPINLAND, pi->getSerial32(), pc->getSerial32() );
	        if (g_bByPass) {
			pi->Refresh();
			return;
		}
        //</Luxor>
		*/
		NxwSocketWrapper sw;
		sw.fillOnline( pi );
		for( sw.rewind(); !sw.isEmpty(); sw++ )
		{
			SendDeleteObjectPkt( sw.getSocket(), pi->getSerial32() );
		}

		pi->MoveTo(pp->TxLoc,pp->TyLoc,pp->TzLoc);
		pi->setContSerial(-1);

		P_ITEM p_boat = Boats->GetBoat(pi->getPosition());

		if(ISVALIDPI(p_boat))
		{
			pi->SetMultiSerial(p_boat->getSerial32());
		}


		pi->Refresh();
	}
	else
	{
		if ( !ItemDroppedOnChar(ps, pp, pi) ) {
			//<Luxor>: Line of sight check
			//This part avoids the circle of transparency walls bug

			//-----
			if ( !lineOfSight( pc->getPosition(), Loc( pp->TxLoc, pp->TyLoc, pp->TzLoc ) ) ) {
		                ps->sysmsg(TRANSLATE("You cannot place an item there!"));

        	        	Sndbounce5(s);
	                	if (ps->isDragging()) {
	                        	ps->resetDragging();
                        		UpdateStatusWindow(s,pi);
                		}
                		pi->setContSerial( pi->getContSerial(true) );
                		pi->setPosition( pi->getOldPosition() );
                		pi->layer = pi->oldlayer;
                		pi->Refresh();
                		return;
        		}
        		//</Luxor>

	        	//<Luxor> Items count check
	        	if (!pc->IsGM()) {
				NxwItemWrapper si;
				si.fillItemsAtXY( pp->TxLoc, pp->TyLoc );
				if (si.size() >= 2) { //Only 2 items permitted
					ps->sysmsg(TRANSLATE("There is not enough space there!"));
					Sndbounce5(s);
					if (ps->isDragging()) {
						ps->resetDragging();
						UpdateStatusWindow(s,pi);
					}
					if (ISVALIDPI(pc->getBackpack())) {
						pi->setCont(pc->getBackpack());
						pi->SetRandPosInCont(pc->getBackpack());
					} else {
						pi->setContSerial( pi->getContSerial(true) );
						pi->setPosition( pi->getOldPosition() );
					}
					pi->layer = pi->oldlayer;
					pi->Refresh();
					return;
				}
			}
        		//</Luxor>
		}

		weights::NewCalc(pc);  // Ison 2-20-99
		statwindow(pc,pc);
		pc->playSFX( itemsfx(pi->getId()) );

		//Boats !
		if (pc->getMultiSerial32() > 0) //How can they put an item in a multi if they aren't in one themselves Cut lag by not checking everytime something is put down
		{
			P_ITEM multi = pointers::findItemBySerial( pc->getMultiSerial32() );
			if (ISVALIDPI(multi))
			{
					//setserial(DEREF_P_ITEM(pi),DEREF_P_ITEM(multi),7);
					pi->SetMultiSerial(multi->getSerial32());
			}
		}
		//End Boats
	}
}
void cCombat::DoCombat(P_CHAR pc_attacker, unsigned int currenttime)
{
	int x, bowtype=0;// spamanachecking, tmp;

	if ( pc_attacker == NULL )
		return;
	if (pc_attacker->free) return;
	P_ITEM pWeapon=pc_attacker->getWeapon();

	P_CHAR pc_defender = FindCharBySerial(pc_attacker->targ);
	/*if (pc_attacker->priv2&2) //The char is paralyzed 
	{ 
        sysmessage(calcSocketFromChar(pc_attacker), "You are frozen and cannot attack."); 
        return; 
	}*/
	if ((pc_defender == NULL) || (pc_defender->isPlayer() && !online(pc_defender) || pc_defender->isHidden()) && pc_attacker->war)
	{
		pc_attacker->war=false; // LB
		pc_attacker->timeout=0;
		pc_attacker->attacker = INVALID_SERIAL;
		pc_attacker->resetAttackFirst();
		return;
	}
	if (( pc_attacker->isNpc() || online(pc_attacker) ) && pc_defender != NULL )
	{			
		if (pc_defender == NULL) return;
		if (pc_defender->free) return;
		if (pc_attacker->dispz > (pc_defender->dispz +10)) return;//FRAZAI
		if (pc_attacker->dispz < (pc_defender->dispz -10)) return;//FRAZAI
		
		if ((pc_defender->isNpc() && pc_defender->npcaitype!=17) || (online(pc_defender) && !pc_defender->dead) ) // ripper		
		{
			if (chardist( pc_attacker, pc_defender ) > SrvParams->attack_distance())
			{
				if (pc_attacker->npcaitype==4 && pc_attacker->inGuardedArea()) // changed from 0x40 to 4, LB
				{
					pc_attacker->moveTo(pc_defender->pos);
					
					teleport(pc_attacker);
					soundeffect2(pc_attacker, 0x01FE); // crashfix, LB
					staticeffect(pc_attacker, 0x37, 0x2A, 0x09, 0x06);
					npctalkall(pc_attacker,"Halt, scoundrel!",1);
				}
				else 
				{ // else -> npcaityes != 4
					pc_attacker->targ = INVALID_SERIAL;
					pc_attacker->timeout=0;
					P_CHAR pc = FindCharBySerial(pc_attacker->attacker);
					if (pc != NULL)
					{
						pc->resetAttackFirst();
						pc->attacker = INVALID_SERIAL; // lb crashfix
					}
					pc_attacker->attacker=INVALID_SERIAL;
					pc_attacker->resetAttackFirst();
					if (pc_attacker->isNpc() && pc_attacker->npcaitype!=17 && !pc_attacker->dead && pc_attacker->war)
						npcToggleCombat(pc_attacker); // ripper
				}
			}
			else
			{
				if (pc_attacker->targ == INVALID_SERIAL)
				{
					npcsimpleattacktarget(pc_attacker, pc_defender);
					x=(((100-pc_attacker->effDex())*MY_CLOCKS_PER_SEC)/25)+(1*MY_CLOCKS_PER_SEC); //Yet another attempt.
					pc_attacker->timeout=currenttime+x;
					return;
				}
				if (Combat->TimerOk(pc_attacker))
				{
					int los = line_of_sight(-1, pc_attacker->pos, pc_defender->pos, WALLS_CHIMNEYS+DOORS+FLOORS_FLAT_ROOFING);
					UOXSOCKET s1 = calcSocketFromChar(pc_attacker);
					int fightskill=Skills->GetCombatSkill(pc_attacker);
					x=0;
					if (fightskill==ARCHERY)
					{
						if (los)
						{
							int arrowsquant;
							bowtype=Combat->GetBowType(pc_attacker);
							if (bowtype==1) 
								arrowsquant=getamount(pc_attacker, 0x0F3F);
							else 
								arrowsquant=getamount(pc_attacker, 0x1BFB);
							if (arrowsquant>0)
								x=1;
							//else
							//	sysmessage(s1, "You are out of ammunitions!"); //-Fraz- this message can cause problems removed
						}
					}
					if ( chardist( pc_attacker, pc_defender )<2 && fightskill!=ARCHERY ) x=1;
					if (x)
					{
						// - Do stamina maths - AntiChrist (6) -
						if(abs(SrvParams->attackstamina())>0 && !pc_attacker->isGM())
						{
							if((SrvParams->attackstamina()<0)&&(pc_attacker->stm<abs(SrvParams->attackstamina())))
							{
								sysmessage(s1, tr("You are too tired to attack."));
								SetWeaponTimeout(pc_attacker, pWeapon);
								return;
							}
							pc_attacker->stm += SrvParams->attackstamina();
							if (pc_attacker->stm>pc_attacker->effDex()) pc_attacker->stm=pc_attacker->effDex();
							if (pc_attacker->stm<0) pc_attacker->stm=0;
							updatestats((pc_attacker),2); //LB, crashfix, was currchar[a]
							// --------ATTACK STAMINA END ------
						}
						
						DoCombatAnimations( pc_attacker, pc_defender, fightskill, bowtype, los);

						if (((chardist( pc_attacker, pc_defender )<2)||(fightskill==ARCHERY))&&!(pc_attacker->npcaitype==4)) // changed from 0x40 to 4
                        {
							if (los)
							{
								npcsimpleattacktarget(pc_attacker, pc_defender);
							}
						}
						if (pc_attacker->timeout2 > uiCurrentTime) return; //check shotclock memory-BackStab
						if (fightskill==ARCHERY)
							Combat->CombatHit(pc_attacker, pc_defender, currenttime,los);
						else
							pc_attacker->swingtarg = pc_defender->serial;
					}

					SetWeaponTimeout(pc_attacker, pWeapon);
					pc_attacker->timeout2=pc_attacker->timeout; // set shotclock memory-BackStab
					if (!pc_defender->isInvul())
					{
						NpcSpellAttack(pc_attacker,pc_defender,currenttime,los);
					}
					if (fightskill!=ARCHERY)
					{
						Combat->CombatHit(pc_attacker, pc_defender, currenttime, los); // LB !!!
						//return; // Ripper	???? (Duke)
					}
				}
			}			
			if (pc_defender->hp<1)//Highlight //Repsys
			{
				if((pc_attacker->npcaitype==4 || pc_attacker->npcaitype==9) && pc_defender->isNpc())
				{
					npcaction(pc_defender, 0x15);
					
					PlayDeathSound(pc_defender);
					
					Npcs->DeleteChar(pc_defender);//Guards, don't give body
				}
				else
				{
					deathstuff(pc_defender);
				}
				//murder count \/
				
				if ((pc_attacker->isPlayer())&&(pc_defender->isPlayer()))//Player vs Player
				{
					if(pc_defender->isInnocent() && GuildCompare(pc_attacker, pc_defender )==0 )
					{
						++pc_attacker->kills;
						UOXSOCKET attacker_socket = calcSocketFromChar(pc_attacker);
						sysmessage(attacker_socket, tr("You have killed %1 innocent people.").arg(pc_attacker->kills));
						//clConsole.send("DEBUG %s's kills are now -> %i\n",pc_attacker->name,pc_attacker->kills);
						if (pc_attacker->kills==SrvParams->maxkills()+1)
							sysmessage(attacker_socket, tr("You are now a murderer!"));
					}
					
					if (SrvParams->pvpLog())
					{
						sprintf((char*)temp,"%s was killed by %s!\n",pc_defender->name.c_str(), pc_attacker->name.c_str());
						savelog((char*)temp,"PvP.log");
					}
					
				}
				npcToggleCombat(pc_attacker);
				return; // LB
			}
		}
	}
}
// CombatHit now expects that LineOfSight has been checked before (Duke, 10.7.2001)
void cCombat::CombatHit(P_CHAR pc_attacker, P_CHAR pc_deffender, unsigned int currenttime, short los)
{
	char hit;

	if (pc_deffender == NULL || pc_attacker == NULL)
		return;

	UOXSOCKET s1=calcSocketFromChar(pc_attacker), s2=calcSocketFromChar(pc_deffender);
	unsigned short fightskill = Skills->GetCombatSkill(pc_attacker), bowtype = Combat->GetBowType(pc_attacker),splitnum,splitcount,hitin;
	unsigned int basedamage;
	int damage; // removed from unsigne by Magius(CHE)
	signed int x;
	// Magius(CHE) - For armour absorbtion system
	int maxabs, maxnohabs, tmpj;


	P_ITEM pWeapon=pc_attacker->getWeapon();// get the weapon item only once

	if (pWeapon && !(rand()%50)	// a 2 percent chance (Duke, 07.11.2000)
		&& pWeapon->type !=9)	// but not for spellbooks (Duke, 09/10/00)
	{
		pWeapon->hp--; //Take off a hit point
		if(pWeapon->hp<=0)
		{
			sysmessage(s1, tr("Your weapon has been destroyed"));
			if ((pWeapon->trigon==1) && (pWeapon->layer>0))// -Frazurbluu- Trigger Type 2 is my new trigger type *-
			{
				Trig->triggerwitem(s1, pWeapon, 1); // trigger is fired when item destroyed
			}				
			Items->DeleItem(pWeapon);
		}
	}

	// End here - Magius(CHE) - For armour absorbtion system



	pc_attacker->swingtarg=-1;

	if((chardist(pc_attacker, pc_deffender)>1 && fightskill!=ARCHERY) || !los) return;
	if(pc_deffender->isNpc() && pc_deffender->isInvul()) return; // ripper


	hit=Skills->CheckSkill(pc_attacker, fightskill, 0, 1000);  // increase fighting skill for attacker and defender
	if (!hit)
	{
		if (pc_attacker->isPlayer())
			doMissedSoundEffect(pc_attacker);
		if ((fightskill==ARCHERY)&&(los))
		{
			if (rand()%3-1)//-1 0 or 1
			{
				short id=0x1BFB;	// bolts
				if (bowtype==1)
					id=0x0F3F;		// arrows

				P_ITEM pAmmo=Items->SpawnItem(pc_deffender,1,"#",1,id,0,0);
				if(pAmmo)
				{
					pAmmo->moveTo(pc_deffender->pos);
					pAmmo->priv=1;
					RefreshItem(pAmmo);
				}
			}
		}
	}
	else
	{
		if (!pc_deffender->isInvul())
		{
			if (pc_deffender->xid==0x0191) soundeffect2(pc_deffender,0x014b);
			else if (pc_deffender->xid==0x0190) soundeffect2(pc_deffender,0x0156);
			playmonstersound(pc_deffender, pc_deffender->id(), SND_DEFEND);
			//AntiChrist -- for poisoned weapons
			if((pWeapon) && (pWeapon->poisoned>0))
			{
				   pc_deffender->poisoned=pWeapon->poisoned;
				   pc_deffender->poisontime=uiCurrentTime+(MY_CLOCKS_PER_SEC*(40/pc_deffender->poisoned)); // a lev.1 poison takes effect after 40 secs, a deadly pois.(lev.4) takes 40/4 secs - AntiChrist
			       pc_deffender->poisonwearofftime=pc_deffender->poisontime+(MY_CLOCKS_PER_SEC*SrvParams->poisonTimer()); //wear off starts after poison takes effect - AntiChrist
			}
			CheckPoisoning(s2, pc_attacker, pc_deffender);	// attacker poisons defender
			CheckPoisoning(s1, pc_deffender, pc_attacker); // and vice versa

			if ((pc_deffender->effDex()>0)) pc_deffender->priv2&=0xFD;	// unfreeze

			if (fightskill!=WRESTLING && los)
				Combat->ItemSpell(pc_attacker, pc_deffender);
			
			if (fightskill!=WRESTLING || pc_attacker->isNpc())
				basedamage=Combat->CalcAtt(pc_attacker); // Calc base damage
			else
			{
				if ((pc_attacker->skill[WRESTLING]/100) > 0) 
				{
					if (pc_attacker->skill[WRESTLING]/100!=0)
						basedamage=rand()%(pc_attacker->skill[WRESTLING]/100);
					else basedamage=0;
				}
				else basedamage=rand()%2;
			}

			if((pc_attacker->isPlayer()) && (fightskill!=WRESTLING))
			{ 
				if (pWeapon->racehate != 0 && pc_deffender->race != 0)//-Fraz- Racehating combat
				{
					if (pWeapon->racehate==pc_deffender->race)
					{
						basedamage *=2;
							if(pc_deffender->isPlayer())
							{
								sysmessage(s2, tr("You scream in agony from being hit by the accursed metal!"));
								if (pc_deffender->xid == 0x0191) soundeffect2(pc_deffender,0x0152);
								else if (pc_deffender->xid==0x0190) soundeffect2(pc_deffender,0x0157);
							}// can add a possible effect below here for npc's being hit
					}
							
				}
			}
			Skills->CheckSkill(pc_attacker, TACTICS, 0, 1000);
			damage=(int)(basedamage*((pc_attacker->skill[TACTICS]+500.0)/1000.0)); // Add Tactical bonus
			damage=damage+(int)((basedamage*(pc_attacker->st/500.0))); // Add Strength bonus

			//Adds a BONUS DAMAGE for ANATOMY
			//Anatomy=100 -> Bonus +20% Damage - AntiChrist (11/10/99)
			if (Skills->CheckSkill(pc_attacker, ANATOMY, 0, 1000))
			{
				float multiplier=(((pc_attacker->skill[ANATOMY]*20)/1000.0f)/100.0f)+1;
				damage=(int)  (damage * multiplier);
			}
			//Adds a BONUS DEFENCE for TACTICS
			//Tactics=100 -> Bonus -20% Damage - AntiChrist (11/10/99)
			float multiplier=1-(((pc_deffender->skill[TACTICS]*20)/1000.0f)/100.0f);
			damage=(int)  (damage * multiplier);
			P_ITEM pShield=pc_deffender->getShield();
			if(pShield)
			{
				if (Skills->CheckSkill(pc_deffender, PARRYING, 0, 1000))// chance to block with shield
				{
					if (pShield->def!=0) damage-=rand()%(pShield->def);// damage absorbed by shield
					if(rand()%2) pShield->hp--; //Take off a hit point
					if(pShield->hp<=0)
					{
						sysmessage(s2, tr("Your shield has been destroyed"));
						if ((pShield->trigon==1) && (pShield->layer >0))// -Frazurbluu- Trigger Type 2 is my new trigger type *-
						{
							Trig->triggerwitem(s2, pShield, 1); // trigger is fired when item destroyed
						}	
						Items->DeleItem(pShield);
					}
				}
			}
			// Armor destruction and sped up by hitting with maces should go in here somewhere 
			// According to lacation of body hit Id imagine -Frazurbluu- **NEEDS ADDED**
			x=rand()%100;// determine area of body hit
			if (!SrvParams->combatHitMessage())
			{
				if (x<=44) x=1; // body
				else if (x<=58) x=2; // arms
				else if (x<=72) x=3; // head
				else if (x<=86) x=4; // legs
				else if (x<=93) x=5; // neck
				else x=6; // hands
			}
			else
			{
				temp[0] = '\0';
				hitin = rand()%2;
				if (x<=44)
				{
					x=1;       // body
					switch (hitin)
					{
					case 1:
						//later take into account dir facing attacker during battle
						if (damage < 10) strcpy(temp, "hits you in your Chest!");
						else if (damage >=10) strcpy(temp, "lands a terrible blow to your Chest!");
						break;
					case 2:
						if (damage < 10) strcpy(temp, "lands a blow to your Stomach!");
						else if (damage >=10) strcpy(temp, "knocks the wind out of you!");
						break;
					default:
						if (damage < 10) strcpy(temp, "hits you in your Ribs!");
						else if (damage >=10) strcpy(temp, "broken your Rib?!");
					}
				}
				else if (x<=58)
				{
					if (damage > 1)
					{
						x=2;  // arms
						switch (hitin)
						{
						case 1:	strcpy(temp, "hits you in Left Arm!");	break;
						case 2:	strcpy(temp, "hits you in Right Arm!");	break;
						default:strcpy(temp, "hits you in Right Arm!");
						}
					}
				}
				else if (x<=72)
				{
					x=3;  // head
					switch (hitin)
					{
					case 1:
						if (damage < 10) strcpy(temp, "hits you you straight in the Face!");
						else if (damage >=10) strcpy(temp, "lands a stunning blow to your Head!");
						break;
					case 2:
						if (damage < 10) strcpy(temp, "hits you to your Head!"); //kolours - (09/19/98)
						else if (damage >=10) strcpy(temp, "smashed a blow across your Face!");
						break;
					default:
						if (damage < 10) strcpy(temp, "hits you you square in the Jaw!");
						else if (damage >=10) strcpy(temp, "lands a terrible hit to your Temple!");
					}
				}
				else if (x<=86) 
				{
					x=4;  // legs
					switch (hitin)
					{
					case 1:	strcpy(temp, "hits you in Left Thigh!");	break;
					case 2:	strcpy(temp, "hits you in Right Thigh!");	break;
					default:strcpy(temp, "hits you in Groin!");
					}
				}
				else if (x<=93)
				{
					x=5;  // neck
					strcpy(temp, "hits you to your Throat!");
				}
				else
				{
					x=6;  // hands
					switch (hitin)
					{
					case 1:
						if (damage > 1) strcpy(temp, tr("hits you in Left Hand!").latin1());
						break;
					case 2:
						if (damage > 1) strcpy(temp, tr("hits you in Right Hand!").latin1());
						break;
					default:
						if (damage > 1) strcpy(temp, tr("hits you in Right Hand!").latin1());
					}
				}

				sprintf((char*)temp2,"%s %s",pc_attacker->name.c_str(), temp);
				if (pc_deffender->isPlayer() && s2!=-1) sysmessage(s2, (char*)temp2); //kolours -- hit display
			}
			x = CalcDef(pc_deffender,x);
			
			// Magius(CHE) - For armour absorbtion system
			maxabs = 20; //
			           // there are monsters with DEF >20, this makes them undefeatable
			maxnohabs=100;
			if (SrvParams->maxAbsorbtion() > 0)
			{
				maxabs = SrvParams->maxAbsorbtion();
			}
			if (SrvParams->maxnohabsorbtion() > 0)
			{
				maxnohabs = SrvParams->maxnohabsorbtion();
			}		
			if (!ishuman(pc_deffender)) maxabs=maxnohabs;
			tmpj=(int) (damage*x)/maxabs; // Absorbtion by Magius(CHE)
			damage -= tmpj;
			if (damage<0) damage=0;
			if (pc_deffender->isPlayer()) damage /= SrvParams->npcdamage(); // Rate damage against other players
			// End Armour Absorbtion by Magius(CHE) (See alse reactive armour spell damage)

			if (pc_attacker->isPlayer())//Zippy
				ItemCastSpell(s1, pc_deffender,pWeapon);

			//AntiChrist - 26/10/99
			//when hitten and damage >1, defender fails if casting a spell!
			if(damage>1 && pc_deffender->isPlayer())//only if damage>1 and against a player
			{
				if(pc_deffender->casting && currentSpellType[s2]==0 )
				{//if casting a normal spell (scroll: no concentration loosen)
					Magic->SpellFail(s2);
					currentSpellType[s2]=0;
					pc_deffender->spell=-1;
					pc_deffender->casting=0;
					pc_deffender->spelltime=0;
					pc_deffender->priv2 &= 0xfd; // unfreeze, bugfix LB
				}
			}

			if(damage>0)
			{
				if (pc_deffender->ra) // For reactive armor spell
				{
					// -Frazurbluu- RA may need a rewrite to be more OSI standard here
					// Its said 80% deflected 10% to attacker / 10% defender gotta check special effects
					int damage1;
					damage1=(int)( damage*(pc_deffender->skill[MAGERY]/2000.0));
					pc_deffender->hp -= damage-damage1;
					if (pc_deffender->isNpc()) damage1 = damage1 * SrvParams->npcdamage(); // by Magius(CHE)
					pc_attacker->hp -= damage1;  // Remove damage from attacker
					staticeffect(pc_deffender, 0x37, 0x4A, 0, 15);//RA effect - AntiChrist (9/99)
					if ((fightskill==MACEFIGHTING) && (IsSpecialMace(pWeapon->id())))// Stamina Loss -Fraz-
					{ 
						//pc_attacker->stm-=3+(rand()%4);
					}
					if ((fightskill==FENCING) && (IsFencing2H(pWeapon->id())))// Paralyzing -Fraz-
					{ 
						//will call the combat caused paralyzation **NEED TO DO**
					}
					if ((fightskill==SWORDSMANSHIP) && (IsAxe(pWeapon->id())))// Concussion Hit -Fraz-
					{ 
						//will call the combat caused concussion (loss of int for 30 secs) **NEED TO DO**
						// for now make it subtract mana
						//pc_attacker->mn-=(pc_attacker->mn/2);
					}
					updatestats(pc_attacker, 0);
				}
				else 
				{	// -Fraz- Now needs adjusted to happen on a skill percentage 
					pc_deffender->hp-=damage; // Remove damage from defender only apply special hits to non-npc's
					if ((fightskill==MACEFIGHTING) && (IsSpecialMace(pWeapon->id())) && (pc_deffender->isPlayer()))// Stamina Loss -Fraz-
					{ 
						pc_deffender->stm-=3+(rand()%3);
					}
					if ((fightskill==FENCING) && (IsFencing2H(pWeapon->id())) && (pc_deffender->isPlayer()))// Paralyzing -Fraz-
					{ 
						tempeffect(pc_attacker, pc_deffender, 44, 0, 0, 0);
						sysmessage(s1, tr("You delivered a paralyzing blow"));
											}
					if ((fightskill==SWORDSMANSHIP) && (IsAxe(pWeapon->id())) && (pc_deffender->isPlayer()))// Concussion Hit -Fraz-
					{ 
						tempeffect(pc_attacker, pc_deffender, 45, 0, 0, 0);
						//pc_attacker->mn-=(pc_attacker->mn/2); //-Fraz- temp use of this for concussion
					}
					updatestats((pc_deffender), 0);
				}
				// blood shred by blackwind
				if (damage>10)
				{
	               short id = 0x122c;	
	               if (damage>50) id=0x122a;
				   else if (damage>40) id=0x122d;
	               else if (damage>30) id=0x122e;
	               else if (damage>20) id=0x122b;
				   P_ITEM pBlood = Items->SpawnItem(pc_deffender, 1, "#", 0, id, 0, 0);
				   if (pBlood)
				   {
					  pBlood->moveTo(pc_deffender->pos);
					  pBlood->priv = 1;
					  pBlood->setGMMovable(); //Moveable by GM
					  RefreshItem(pBlood);
					  pBlood->decaytime = (SrvParams->decayTime()/2)*MY_CLOCKS_PER_SEC+uiCurrentTime;
				   }
				}

				/////////  For Splitting NPCs ///  McCleod
				if ((pc_deffender->split>0)&&(pc_deffender->hp>=1))
				{
					if (rand()%100<=pc_deffender->splitchnc)
					{
						if (pc_deffender->split==1) splitnum=1;
						else splitnum=rand()%pc_deffender->split+1;
						
						for (splitcount=0;splitcount<splitnum;splitcount++)
							Npcs->Split(pc_deffender);
					}
				}
				////////      End of spliting NPCs
			}
			if (pc_attacker->isPlayer())
				if((fightskill==ARCHERY && los)|| fightskill!=ARCHERY)
					doSoundEffect(pc_attacker, fightskill, pWeapon);
			if (pc_deffender->hp<0) pc_deffender->hp=0;
			updatestats((pc_deffender), 0);
			x = pc_deffender->id();
			if (x>=0x0190)
			{
				if (!pc_deffender->onhorse) 
					npcaction(pc_deffender, 0x14);
			}
		}
	}
}