// Formulas take from OSI's combat formulas // attack speed should be determined here. // attack speed = 15000 / ((DEX+100) * weapon speed) static void SetWeaponTimeout(P_CHAR Attacker, P_ITEM Weapon) { int x,j; if (Weapon) { if (Weapon->spd==0) Weapon->spd=35; x = (15000*MY_CLOCKS_PER_SEC) / ((Attacker->effDex()+100) * Weapon->spd); //Calculate combat delay } else { if(Attacker->skill[WRESTLING]>200) j = 35; else if(Attacker->skill[WRESTLING]>400) j = 40; else if(Attacker->skill[WRESTLING]>600) j = 45; else if(Attacker->skill[WRESTLING]>800) j = 50; else j = 30; x = (15000*MY_CLOCKS_PER_SEC) / ((Attacker->effDex()+100) * j); } Attacker->timeout=uiCurrentTime+x; }
bool cAllTmpEff::Add(P_CHAR pc_source, P_CHAR pc_dest, int num, unsigned char more1, unsigned char more2, unsigned char more3, short dur) { unsigned int ic; // antichrist' changes int color, color1, color2, socket; //used for incognito spell int loopexit=0; if ( pc_source == NULL || pc_dest == NULL ) return false; if (teffectcount>=cmem*5) return false; cTmpEff *pTE; for (ic=0; ic<teffectcount; ic++) // If there is already an effect of the same or similar kind, reverse it first (Duke) { pTE = &teffects[ic]; if (pTE->getDest() == pc_dest->serial) { if ((pTE->num==3 && num==3)|| (pTE->num==4 && num==4)|| (pTE->num==5 && num==5)|| (pTE->num==6 && num==6)|| (pTE->num==7 && num==7)|| (pTE->num==8 && num==8)|| (pTE->num==11&& num==11)|| (pTE->num==12&& num==12)|| (pTE->num==18&& num==18)|| //added Poly reverse - AntiChrist (9/99) (pTE->num==21&& num==21)|| (pTE->num==19&& num==19)|| //added Incognito reverse - AntiChrist (12/99) (pTE->num==18&& num==19)|| //reverse poly effect if we have to use incognito - AntiChrist (12/99) (pTE->num==19&& num==18) ) //reverse incognito effect if we have to use poly - AntiChrist (12/99) { pTE->Reverse(); AllTmpEff->Remove(pTE); } } } pTE=new cTmpEff; pTE->Init(); pTE->setSour(pc_source->serial); pTE->setDest(pc_dest->serial); pTE->num=num; switch (num) { case 1: pc_dest->priv2 |= 0x02; pTE->setExpiretime_s(pc_source->skill[MAGERY]/100); pTE->more1=0; pTE->more2=0; pTE->dispellable=1; break; case 2: // night sight pc_dest->fixedlight=worldbrightlevel; dolight(calcSocketFromChar((pc_dest)), worldbrightlevel); Magic->afterParticles(6, pc_dest); // shows particles for UO:3D clients, like On OSI servers if(dur > 0) // if a duration is given (potions), use that (Duke, 30.12.2000) pTE->setExpiretime_s(dur); else pTE->setExpiretime_s(pc_source->skill[MAGERY]*10); pTE->more1=0; pTE->more2=0; pTE->dispellable=1; break; case 3: if (pc_dest->effDex()<more1) more1=pc_dest->effDex(); pc_dest->chgDex(-1 * more1); pc_dest->stm=min(pc_dest->stm, (int)pc_dest->effDex()); statwindow(calcSocketFromChar(pc_dest), pc_dest); pTE->setExpiretime_s(pc_source->skill[MAGERY]/10); pTE->more1=more1; pTE->more2=0; pTE->dispellable=1; break; case 4: if (pc_dest->in<more1) more1=pc_dest->in; pc_dest->in-=more1; pc_dest->mn=min(pc_dest->mn, pc_dest->in); statwindow(calcSocketFromChar(pc_dest), pc_dest); pTE->setExpiretime_s(pc_source->skill[MAGERY]/10); pTE->more1=more1; pTE->more2=0; pTE->dispellable=1; break; case 5: if (pc_dest->st<more1) more1=pc_dest->st; pc_dest->st-=more1; pc_dest->hp=min(pc_dest->hp, pc_dest->st); statwindow(calcSocketFromChar(pc_dest), pc_dest); pTE->setExpiretime_s(pc_source->skill[MAGERY]/10); pTE->more1=more1; pTE->more2=0; pTE->dispellable=1; break; case 6: if (pc_dest->effDex()+more1>250) more1=250-pc_dest->effDex(); pc_dest->chgDex(more1); statwindow(calcSocketFromChar(pc_dest), pc_dest); if(dur > 0) // if a duration is given (potions), use that (Duke, 31.10.2000) pTE->setExpiretime_s(dur); else pTE->setExpiretime_s(pc_source->skill[MAGERY]/10); pTE->more1=more1; pTE->more2=0; pTE->dispellable=1; break; case 7: if (pc_dest->in+more1>255) more1=pc_dest->in-255; pc_dest->in+=more1; statwindow(calcSocketFromChar(pc_dest), pc_dest); pTE->setExpiretime_s(pc_source->skill[MAGERY]/10); pTE->more1=more1; pTE->more2=0; pTE->dispellable=1; break; case 8: if (pc_dest->st+more1>255) more1=pc_dest->st-255; pc_dest->st+=more1; statwindow(calcSocketFromChar(pc_dest), pc_dest); if(dur > 0) // if a duration is given (potions), use that (Duke, 31.10.2000) pTE->setExpiretime_s(dur); else // else use caster's skill pTE->setExpiretime_s(pc_source->skill[MAGERY]/10); pTE->more1=more1; pTE->more2=0; pTE->dispellable=1; break; case 9: pTE->setExpiretime_s(more2); pTE->more1=more1; pTE->more2=more2; break; case 10: pTE->setExpiretime_s(12); pTE->more1=more1; pTE->more2=more2; break; case 11: // Bless if (pc_dest->st+more1>255) more1=pc_dest->st-255; if (pc_dest->effDex()+more2>250) more2=250-pc_dest->effDex(); if (pc_dest->in+more3>255) more3=pc_dest->in-255; pc_dest->st+=more1; pc_dest->chgDex(more2); pc_dest->in+=more3; statwindow(calcSocketFromChar(pc_dest), pc_dest); pTE->setExpiretime_s(pc_source->skill[MAGERY]/10); pTE->more1=more1; pTE->more2=more2; pTE->more3=more3; pTE->dispellable=1; break; case 12: // Curse if (pc_dest->st<more1) more1=pc_dest->st; if (pc_dest->effDex()<more2) more2=pc_dest->effDex(); if (pc_dest->in<more3) more3=pc_dest->in; pc_dest->st-=more1; pc_dest->chgDex(-1 * more2); pc_dest->in-=more3; statwindow(calcSocketFromChar(pc_dest), pc_dest); pTE->setExpiretime_s(pc_source->skill[MAGERY]/10); pTE->more1=more1; pTE->more2=more2; pTE->more3=more3; pTE->dispellable=1; break; case 15: // Reactive armor pTE->setExpiretime_s(pc_source->skill[MAGERY]/10); pTE->dispellable=1; break; case 16: //Explosion potions Tauriel pTE->setExpiretime_s(more2); pTE->more1=more1; //item/potion pTE->more2=more2; //seconds pTE->more3=more3; //countdown# break; case 18: //Polymorph - AntiChrist 09/99 pTE->setExpiretime_s(polyduration); int c1,b,k; //Grey flag when polymorphed - AntiChrist (9/99) pc_dest->crimflag=(polyduration*MY_CLOCKS_PER_SEC)+uiCurrentTime; if(pc_dest->onhorse) k = unmounthorse(calcSocketFromChar(pc_dest)); k=(more1<<8)+more2; pc_dest->xid = pc_dest->id();//let's backup previous id if (k>=0x000 && k<=0x3e1) // lord binary, body-values >0x3e crash the client { pc_dest->id1=k>>8; // allow only non crashing ones pc_dest->id2=k%256; c1 = pc_dest->skin; // transparency for monsters allowed, not for players, // if polymorphing from monster to player we have to switch from transparent to semi-transparent b=c1&0x4000; if (b==16384 && (k >=0x0190 && k<=0x03e1)) { if (c1!=0x8000) { pc_dest->skin = pc_dest->xskin = 0xF000; } } } pc_dest->polymorph=true; break; case 19://incognito spell - AntiChrist (10/99)//revised by AntiChrist - 9/12/99 { pTE->setExpiretime_s(90); //AntiChrist 11/11/99 //If char is already under polymorph effect, let's reverse the //polymorph effect to avoid problems if(pc_dest->polymorph) { pc_dest->setId(pc_dest->xid); pc_dest->polymorph=false; teleport(pc_dest); } int j; //first: let's search for beard and hair serial //(we could use alredy saved serials...but it's better //to recalculate them) pc_dest->hairserial=-1; pc_dest->beardserial=-1; P_ITEM pi; unsigned int ci; vector<SERIAL> vecContainer = contsp.getData(pc_dest->serial); for ( ci = 0; ci < vecContainer.size(); ci++) { pi = FindItemBySerial(vecContainer[ci]); if(pi->layer==0x10)//beard pc_dest->beardserial=pi->serial; if(pi->layer==0x0B)//hairs pc_dest->hairserial=pi->serial; } // ------ SEX ------ pc_dest->xid = pc_dest->id(); pc_dest->id1=0x01; //if we already have a beard..can't turn to female if(pc_dest->beardserial>-1) { //if character has a beard...only male pc_dest->id2='\x90';//male } else { //if no beard let's randomly change if((rand()%2)==0) pc_dest->id2='\x90';//male else pc_dest->id2='\x91';//or female } // --- SKINCOLOR --- pc_dest->xskin = pc_dest->skin; color=rand()%6; switch(color) { case 0: pc_dest->skin = 0x83EA; break; case 1: pc_dest->skin = 0x8405; break; case 2: pc_dest->skin = 0x83EF; break; case 3: pc_dest->skin = 0x83F5; break; case 4: pc_dest->skin = 0x841C; break; case 5: pc_dest->skin = 0x83FB; break; default: break; } // ------ NAME ----- pc_dest->orgname = pc_dest->name; if(pc_dest->id2==0x90) setrandomname(pc_dest, "1");//get a name from male list else setrandomname(pc_dest, "2");//get a name from female list // //damn..this formula seems to include also some bad color... //i'll test this later //AntiChrist // //use unique color for hair&beard //color=0x044E+(rand()%(0x04AD-0x044E)); //i had to track down some valid value //for hair/beard colors, cause that //formula contained some bad value =( //but now it works perfectly :) //AntiChrist-11/11/99 color=rand()%8; switch(color) { case 0: color=0x044e; break; case 1: color=0x0455; break; case 2: color=0x045e; break; case 3: color=0x0466; break; case 4: color=0x046a; break; case 5: color=0x0476; break; case 6: color=0x0473; break; case 7: color=0x047c; break; default://it should not go here...but..who nows =P color=0x044e; } color1=color>>8; color2=color%256; // ------ HAIR ----- if(pc_dest->hairserial>-1)//if hairs exist { //change hair style/color P_ITEM pHair = FindItemBySerial(pc_dest->hairserial); if(pHair) { //stores old hair values... pHair->moreb1 = static_cast<unsigned char>(pHair->color>>8); pHair->moreb2 = static_cast<unsigned char>(pHair->color%256); pHair->moreb3=pHair->id1; pHair->moreb4=pHair->id2; //and change them with random ones switch(rand()%10) { case 0: pHair->id2='\x3B'; break; case 1: pHair->id2='\x3C'; break; case 2: pHair->id2='\x3D'; break; case 3: pHair->id2='\x44'; break; case 4: pHair->id2='\x45'; break; case 5: pHair->id2='\x46'; break; case 6: pHair->id2='\x47'; break; case 7: pHair->id2='\x48'; break; case 8: pHair->id2='\x49'; break; case 9: pHair->id2='\x4A'; break; default: pHair->id2='\x4A'; break; } //random color pHair->color = color; //let's check for invalid values if ( pHair->color < 0x044E || pHair->color > 0x04AD ) { pHair->color = 0x044E; } pHair->incognito = true;//AntiChrist }//if j!=-1 }//if hairserial!=-1 // -------- BEARD -------- if(pc_dest->id2==0x90)// only if a man if(pc_dest->beardserial>-1)//if beard exist { //change beard style/color P_ITEM pBeard = FindItemBySerial(pc_dest->beardserial); if(pBeard) { //clConsole.send("BEARD FOUND!!\n"); //stores old beard values pBeard->moreb1 = static_cast<unsigned char>(pBeard->color>>8); pBeard->moreb2 = static_cast<unsigned char>(pBeard->color%256); pBeard->moreb3 = static_cast<unsigned char>(pBeard->id() >> 8); pBeard->moreb4 = static_cast<unsigned char>(pBeard->id()%256); //changes them with random ones switch(rand()%7) { case 0: pBeard->id2='\x3E'; break; case 1: pBeard->id2='\x3F'; break; case 2: pBeard->id2='\x40'; break; case 3: pBeard->id2='\x41'; break; case 4: pBeard->id2='\x4B'; break; case 5: pBeard->id2='\x4C'; break; case 6: pBeard->id2='\x4D'; break; default: pBeard->id2='\x4D'; break; } //random color pBeard->color = color; if ( pBeard->color < 0x044E || pBeard->color > 0x04AD ) { pBeard->color = 0x044E; } pBeard->incognito=true;//AntiChrist }//if j!=-1 }//if beardserial!=-1
void cDragItems::equipItem( P_CLIENT client ) { // Get the packet information SERIAL itemId = LongFromCharPtr( &buffer[ client->socket() ][ 1 ] ); SERIAL playerId = LongFromCharPtr( &buffer[ client->socket() ][ 6 ] ); P_ITEM pItem = FindItemBySerial( itemId ); P_CHAR pWearer = FindCharBySerial( playerId ); if( !pItem || !pWearer ) return; P_CHAR pChar = client->player(); // We're dead and can't do that if( pChar->dead ) { client->sysMessage( "You are dead and can't do that." ); bounceItem( client, pItem ); return; } // Our target is dead if( ( pWearer != pChar ) && pWearer->dead ) { client->sysMessage( "You can't equip dead players." ); bounceItem( client, pItem ); return; } // Get our tile-information tile_st pTile; Map->SeekTile( pItem->id(), &pTile ); // Is the item wearable ? ( layer == 0 | equip-flag not set ) // Multis are not wearable are they :o) if( pTile.layer == 0 || !( pTile.flag3 & 0x40 ) || pItem->isMulti() ) { client->sysMessage( "This item cannot be equipped." ); bounceItem( client, pItem ); return; } // Required Strength if( pItem->st > pWearer->st ) { if( pWearer == pChar ) client->sysMessage( "You cannot wear that item, you seem not strong enough" ); else client->sysMessage( "This person can't wear that armor, it seems not strong enough" ); bounceItem( client, pItem ); return; } // Required Dexterity if( pItem->dx > pWearer->effDex() ) { if( pWearer == pChar ) client->sysMessage( "You cannot wear that item, you seem not agile enough" ); else client->sysMessage( "This person can't wear that armor, it seems not agile enough" ); bounceItem( client, pItem ); return; } // Required Intelligence if( pItem->in > pWearer->in ) { if( pWearer == pChar ) client->sysMessage( "You cannot wear that item, you seem not smart enough" ); else client->sysMessage( "This person can't wear that armor, it seems not smart enough" ); bounceItem( client, pItem ); return; } // Males can't wear female armor if( ( pChar->id() == 0x0190 ) && ( pItem->id() >= 0x1C00 ) && ( pItem->id() <= 0x1C0D ) ) { client->sysMessage( "You cannot wear female armor." ); bounceItem( client, pItem ); return; } // Needs a check (!) // Checks for equipment on the same layer // If there is any it tries to unequip it // If that fails it cancels UI08 layer = pItem->layer(); vector< SERIAL > equipment = contsp.getData( pWearer->serial ); for( UI32 i = 0; i < equipment.size(); i++ ) { P_ITEM pEquip = FindItemBySerial( equipment[ i ] ); if( pEquip ) continue; // We found an item which is on the same layer (!) // Unequip it if we can bool twoHanded = false; if( pEquip->twohanded() && ( layer == 1 || layer == 2 ) ) twoHanded = true; if( pItem->twohanded() && ( pEquip->layer() == 1 || pEquip->layer() == 2 ) ) twoHanded = true; if( ( pEquip->layer() == layer ) || twoHanded ) { if( pChar->canPickUp( pEquip ) ) // we're equipping so we do the check pEquip->toBackpack( pWearer ); // If it's still on the char: cancel equipment if( pEquip->contserial == pWearer->serial ) { client->sysMessage( "You already have an item on that layer." ); bounceItem( client, pItem ); return; } } } // At this point we're certain that we can wear the item pItem->setContSerial( playerId ); pItem->setLayer( pTile.layer ); // Don't trust the user input on this one // Handle the weight if the item is leaving our "body" if( pWearer != pChar ) { pChar->weight -= pItem->getWeight(); pWearer->weight += pItem->getWeight(); // Update the status-windows statwindow( client->socket(), pChar ); statwindow( calcSocketFromChar( pWearer ), pWearer ); } if( pTile.layer == 0x19 ) pWearer->setOnHorse( true ); // Apply the bonuses pWearer->st += pItem->st2; pWearer->chgDex( pItem->dx2 ); pWearer->in += pItem->in2; // Show debug information if requested if( showlayer ) clConsole.send( QString( "Item (%1) equipped on layer %2" ).arg( pItem->name() ).arg( pItem->layer() ) ); // I don't think we need to remove the item // as it's only visible to the current char // And he looses contact anyway // SndRemoveitem( pi->serial ); // Build our packets cWornItems wearItem( pWearer->serial, pItem->serial, pItem->layer(), pItem->id(), pItem->color() ); cSoundEffect soundEffect( 0x57, pWearer->pos ); // Send to all sockets in range // ONLY the new equipped item and the sound-effect for( UOXSOCKET s = 0; s < now; s++ ) if( perm[s] && inrange1p( pWearer, currchar[s] ) ) { soundEffect.send( s ); wearItem.send( s ); } // Lord Binaries Glow stuff if( pItem->glow != INVALID_SERIAL ) { pChar->removeHalo( pItem ); pWearer->addHalo( pItem ); pWearer->glowHalo( pItem ); } }
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); } } } }