// This checks LineOfSight before calling CombatHit (Duke, 10.7.2001) void cCombat::CombatHitCheckLoS(P_CHAR pAttacker, unsigned int currenttime) { P_CHAR pDefender = FindCharBySerial(pAttacker->swingtarg); if ( pDefender == NULL ) return; UOXSOCKET s1=calcSocketFromChar(pAttacker); unsigned short los=line_of_sight(s1,pAttacker->pos, pDefender->pos, WALLS_CHIMNEYS+DOORS+FLOORS_FLAT_ROOFING); CombatHit(pAttacker, pDefender, currenttime, los); }
static int fire_torp(struct shpstr *sp, struct shpstr *targ, int ntargets) { int range, erange, dam; if ((mchr[targ->shp_type].m_flags & M_SUB) && (mchr[sp->shp_type].m_flags & M_SUBT) == 0) return 0; /* need sub-torp to torpedo a sub */ erange = roundrange(torprange(sp)); range = mapdist(sp->shp_x, sp->shp_y, targ->shp_x, targ->shp_y); if (range > erange) return 0; if (!line_of_sight(NULL, sp->shp_x, sp->shp_y, targ->shp_x, targ->shp_y)) return 0; dam = shp_torp(sp, 1); putship(sp->shp_uid, sp); if (dam < 0) return 0; pr("Captain! Torpedoes sighted!\n"); if (chance(shp_torp_hitchance(sp, range))) { pr("BOOM!...\n"); if (!(mchr[targ->shp_type].m_flags & M_SUB)) { if (mchr[sp->shp_type].m_flags & M_SUB) nreport(targ->shp_own, N_TORP_SHIP, 0, 1); else nreport(targ->shp_own, N_SHIP_TORP, sp->shp_own, 1); } if (sp->shp_own != 0) wu(0, sp->shp_own, "%s @ %s torpedoed %s\n", prship(sp), xyas(sp->shp_x, sp->shp_y, sp->shp_own), prsub(targ)); if (ntargets > 2) dam /= ntargets / 2; shipdamage(targ, dam); putship(targ->shp_uid, targ); } else { pr("Missed!\n"); if (sp->shp_own != 0) wu(0, sp->shp_own, "%s missed %s with a torpedo at %s\n", prship(sp), prsub(targ), xyas(sp->shp_x, sp->shp_y, sp->shp_own)); } return 1; }
int update_sight(character *player, npc *monster, cell_t *cell_arr) { if(!(line_of_sight(monster, player, cell_arr))) { return 0; } monster->seen_x = player->x_pos; monster->seen_y = player->y_pos; return 1; }
void cDragItems::dropOnGround( P_CLIENT client, P_ITEM pItem, const Coord_cl &pos ) { P_CHAR pChar = client->player(); // Check if the destination is in line of sight if( !line_of_sight( client->socket(), pChar->pos, pos, TREES_BUSHES|WALLS_CHIMNEYS|DOORS|ROOFING_SLANTED|FLOORS_FLAT_ROOFING|LAVA_WATER ) ) { client->sysMessage( "You cannot see the target." ); bounceItem( client, pItem ); return; } if( !pChar->canPickUp( pItem ) ) { bounceItem( client, pItem ); return; } pItem->setContSerial( INVALID_SERIAL ); pItem->moveTo( pos ); pItem->setLayer( 0 ); RefreshItem( pItem ); // Send it to all clients in range pChar->weight -= pItem->getWeight(); statwindow( client->socket(), pChar ); // Update our weight-stats if( pItem->glow != INVALID_SERIAL ) { pChar->removeHalo( pItem ); pChar->glowHalo( pItem ); } // Multi handling (Hm i don't like that...) if( pChar->multis > 0 ) { P_ITEM pMulti = FindItemBySerial( pChar->multis ); if( pMulti != NULL ) { pMulti = findmulti( pItem->pos ); if( pItem != NULL ) pItem->SetMultiSerial( pMulti->serial ); } } }
int sona(void) { struct nstr_item ni, nit; struct sctstr sect; struct shpstr ship; struct shpstr targ; struct natstr *natp; struct mchrstr *mcp; struct mchrstr *tmcp; struct nstr_sect ns; int range; int visib, pingrange; int srange; int vrange; int dist; int x, y; int cx, cy; int changed = 0; int row; /* Where these are used are non-re-entrant, so we keep 'em around */ static char **rad = NULL; static char *radbuf = NULL; static signed char **vis = NULL; static signed char *visbuf = NULL; if (!snxtitem(&ni, EF_SHIP, player->argp[1], NULL)) return RET_SYN; if (!radbuf) radbuf = malloc(WORLD_Y * MAPWIDTH(1)); if (!visbuf) visbuf = malloc(WORLD_Y * MAPWIDTH(1)); if (!rad && radbuf) { rad = malloc(WORLD_Y * sizeof(char *)); if (rad) { for (x = 0; x < WORLD_Y; x++) { rad[x] = &radbuf[(WORLD_X + 1) * x]; } } } if (!vis && visbuf) { vis = malloc(WORLD_Y * sizeof(signed char *)); if (vis) { for (x = 0; x < WORLD_Y; x++) { vis[x] = &visbuf[(WORLD_X + 1) * x]; } } } if (!radbuf || !visbuf || !rad || !vis) { pr("Memory error, tell the deity.\n"); logerror("malloc failed in sona\n"); return RET_FAIL; } while (nxtitem(&ni, &ship)) { if (!player->owner) continue; mcp = &mchr[(int)ship.shp_type]; if (!(mcp->m_flags & M_SONAR)) continue; getsect(ship.shp_x, ship.shp_y, §); if (sect.sct_type != SCT_WATER) continue; range = (int)techfact(ship.shp_tech, mcp->m_vrnge); srange = MIN(7, 7 * range * ship.shp_effic / 200); pr("%s at %s efficiency %d%%, max range %d\n", prship(&ship), xyas(ship.shp_x, ship.shp_y, player->cnum), ship.shp_effic, srange); snxtsct_dist(&ns, ship.shp_x, ship.shp_y, srange); blankfill(radbuf, &ns.range, 1); while (nxtsct(&ns, §)) { if (player->owner || sect.sct_type == SCT_WATER) rad[ns.dy][ns.dx] = dchr[sect.sct_type].d_mnem; else { rad[ns.dy][ns.dx] = '?'; } } snxtsct_dist(&ns, ship.shp_x, ship.shp_y, srange); cx = deltx(&ns.range, ship.shp_x); cy = delty(&ns.range, ship.shp_y); while (nxtsct(&ns, §)) { if (!line_of_sight(rad, cx, cy, ns.dx, ns.dy)) { rad[ns.dy][ns.dx] = ' '; continue; } if (ship.shp_tech >= 310 && sect.sct_type == SCT_WATER) { if (sect.sct_mines) { pr("Sonar detects %d mines in %s!\n", sect.sct_mines, xyas(sect.sct_x, sect.sct_y, player->cnum)); rad[ns.dy][ns.dx] = 'X'; } } changed |= map_set(player->cnum, sect.sct_x, sect.sct_y, rad[ns.dy][ns.dx], 0); } memset(visbuf, 0, (WORLD_Y * (WORLD_X + 1))); snxtitem_dist(&nit, EF_SHIP, ship.shp_x, ship.shp_y, range); while (nxtitem(&nit, &targ)) { if (targ.shp_own == player->cnum || targ.shp_own == 0) continue; tmcp = &mchr[(int)targ.shp_type]; visib = shp_visib(&targ); pingrange = MIN(7, MAX(visib, 10) * range / 10); vrange = pingrange * ship.shp_effic / 200; dist = mapdist(targ.shp_x, targ.shp_y, ship.shp_x, ship.shp_y); pingrange = (MAX(pingrange, 2) * targ.shp_effic) / 100; if (dist > pingrange) continue; if (tmcp->m_flags & M_SONAR && targ.shp_own) { natp = getnatp(targ.shp_own); if (natp->nat_flags & NF_SONAR) wu(0, targ.shp_own, "Sonar ping from %s detected by %s!\n", xyas(ship.shp_x, ship.shp_y, targ.shp_own), prship(&targ)); if (targ.shp_rflags & RET_SONARED) retreat_ship(&targ, targ.shp_own, 's'); } if (dist > vrange) continue; x = deltx(&ns.range, (int)targ.shp_x); y = delty(&ns.range, (int)targ.shp_y); if (rad[y][x] != dchr[SCT_WATER].d_mnem && rad[y][x] != 'X') continue; if (tmcp->m_flags & M_SUB && relations_with(targ.shp_own, player->cnum) < FRIENDLY) { if (mcp->m_vrnge + visib < 8) pr("Sonar detects sub #%d @ %s\n", targ.shp_uid, xyas(targ.shp_x, targ.shp_y, player->cnum)); else if (mcp->m_vrnge + visib < 10) pr("Sonar detects %s @ %s\n", prship(&targ), xyas(targ.shp_x, targ.shp_y, player->cnum)); else pr("Sonar detects %s %s @ %s\n", cname(targ.shp_own), prship(&targ), xyas(targ.shp_x, targ.shp_y, player->cnum)); } else pr("Sonar detects %s %s @ %s\n", cname(targ.shp_own), prship(&targ), xyas(targ.shp_x, targ.shp_y, player->cnum)); if (visib > vis[y][x]) { vis[y][x] = visib; /* &~0x20 makes it a cap letter */ rad[y][x] = (*mchr[(int)targ.shp_type].m_name) & ~0x20; } } if (!player->argp[2]) { rad[cy][cx] = '0'; for (row = 0; row < ns.range.height; row++) if (!blankrow(rad[row])) pr("%s\n", rad[row]); } pr("\n"); } if (changed) writemap(player->cnum); return RET_OK; }
int torp(void) { natid vshipown; int range; int dam; int subno; int victno; int erange; double hitchance; struct shpstr vship; struct shpstr sub; struct mchrstr *sub_mcp; char *ptr; struct nstr_item nbst; char buf[1024]; int ntorping = 0; char prompt[128]; if (!snxtitem(&nbst, EF_SHIP, player->argp[1], "From ship(s)? ")) return RET_SYN; while (nxtitem(&nbst, &sub)) { if (sub.shp_own != player->cnum) continue; if ((mchr[(int)sub.shp_type].m_flags & M_TORP) == 0) continue; if (sub.shp_item[I_GUN] == 0 || sub.shp_item[I_SHELL] < SHP_TORP_SHELLS) continue; if (sub.shp_item[I_MILIT] < 1) continue; if (sub.shp_effic < 60) continue; if (sub.shp_mobil <= 0) continue; ntorping++; } pr("%d ships are eligible to torpedo\n", ntorping); snxtitem_rewind(&nbst); while (nxtitem(&nbst, &sub)) { if (!sub.shp_own) continue; if (sub.shp_own != player->cnum) { continue; } sub_mcp = &mchr[sub.shp_type]; if (!(sub_mcp->m_flags & M_TORP)) { pr("Ship # %d: A %s can't fire torpedoes!\n", sub.shp_uid, sub_mcp->m_name); continue; } if (sub.shp_item[I_GUN] == 0 || sub.shp_item[I_SHELL] < SHP_TORP_SHELLS) { pr("Ship #%d has insufficient armament\n", sub.shp_uid); continue; } if (sub.shp_item[I_MILIT] < 1) { pr("Ship #%d has insufficient crew\n", sub.shp_uid); continue; } if (sub.shp_effic < 60) { pr("Ship #%d torpedo tubes inoperative.\n", sub.shp_uid); continue; } if (sub.shp_mobil <= 0) { pr("Ship #%d has insufficient mobility\n", sub.shp_uid); continue; } subno = sub.shp_uid; sprintf(prompt, "Ship %d, target? ", sub.shp_uid); if (!(ptr = getstarg(player->argp[2], prompt, buf))) return RET_SYN; if (!check_ship_ok(&sub)) return RET_FAIL; if ((victno = atoi(ptr)) < 0) return RET_SYN; if (!getship(victno, &vship)) return RET_FAIL; if (!vship.shp_own) return RET_FAIL; vshipown = vship.shp_own; if (victno == subno) { pr("Shooting yourself, eh? How strange...\n"); continue; } if (mchr[(int)vship.shp_type].m_flags & M_SUB) { if (!(sub_mcp->m_flags & M_SUBT)) { pr("You can't torpedo a submarine!\n"); continue; } } dam = shp_torp(&sub, 1); sub.shp_mission = 0; putship(sub.shp_uid, &sub); if (CANT_HAPPEN(dam < 0)) { pr("Ship #%d has insufficient armament\n", sub.shp_uid); continue; } if (!(sub_mcp->m_flags & M_SUB)) { pr("Starting our attack run...\n"); anti_torp(sub.shp_uid, ntorping, vshipown); } getship(sub.shp_uid, &sub); if (sub.shp_own == 0) continue; erange = roundrange(torprange(&sub)); pr("Effective torpedo range is %d.0\n", erange); pr("Whooosh... "); getship(victno, &vship); vshipown = vship.shp_own; range = mapdist(sub.shp_x, sub.shp_y, vship.shp_x, vship.shp_y); hitchance = shp_torp_hitchance(&sub, range); if (range <= erange) { pr("Hitchance = %.0f%%\n", hitchance * 100); } if (range > erange) pr("Out of range\n"); else if (!line_of_sight(NULL, sub.shp_x, sub.shp_y, vship.shp_x, vship.shp_y)) { pr("BOOM!... Torpedo slams into land before reaching target.\n"); /* We only tell the victim if we were within range. */ if (vshipown != 0 && vshipown != player->cnum) wu(0, vshipown, "Torpedo sighted @ %s by %s\n", xyas(sub.shp_x, sub.shp_y, vshipown), prship(&vship)); } else if (chance(hitchance)) { pr("BOOM!...\n"); if (vshipown != 0 && vshipown != player->cnum) wu(0, vshipown, "%s in %s torpedoed %s for %d damage.\n", sub_mcp->m_flags & M_SUB ? "sub" : prship(&sub), xyas(sub.shp_x, sub.shp_y, vshipown), prship(&vship), dam); pr("Torpedo hit %s for %d damage.\n", prsub(&vship), dam); if (!(mchr[vship.shp_type].m_flags & M_SUB)) { if (mchr[sub.shp_type].m_flags & M_SUB) nreport(vshipown, N_TORP_SHIP, 0, 1); else nreport(vshipown, N_SHIP_TORP, player->cnum, 1); } shipdamage(&vship, dam); if (vship.shp_effic < SHIP_MINEFF) pr("%s sunk!\n", prsub(&vship)); if (vship.shp_rflags & RET_TORPED) retreat_ship(&vship, vshipown, 't'); putship(vship.shp_uid, &vship); } else { pr("Missed\n"); if (vshipown != 0 && vshipown != player->cnum) wu(0, vshipown, "Torpedo sighted @ %s by %s\n", xyas(sub.shp_x, sub.shp_y, vshipown), prship(&vship)); } if (sub_mcp->m_flags & M_SUB) anti_torp(sub.shp_uid, ntorping, vshipown); } return RET_OK; }
// New Class implementation void cDragItems::grabItem( P_CLIENT client ) { // Get our character P_CHAR pChar = client->player(); if( pChar == NULL ) return; // Fetch the grab information SERIAL iSerial = LongFromCharPtr( &buffer[ client->socket() ][ 1 ] ); UI16 amount = ShortFromCharPtr( &buffer[ client->socket() ][ 5 ] ); P_ITEM pItem = FindItemBySerial( iSerial ); if( !pItem ) return; // Are we already dragging an item ? // Bounce it and reject the move // (Logged out while dragging an item) if( client->dragging() ) { bounceItem( client, client->dragging() ); bounceItem( client, pItem, true ); return; } // Do we really want to let him break his meditation // When he picks up an item ? // Maybe a meditation check here ?!? pChar->disturbMed( client->socket() ); // Meditation P_CHAR itemOwner = GetPackOwner( pItem, 64 ); // Try to pick something out of another characters posessions if( itemOwner && ( itemOwner != pChar ) && ( !pChar->Owns( itemOwner ) ) ) { client->sysMessage( QString( "You have to steal the %1 out of %2's posessions." ).arg( pItem->getName() ).arg( itemOwner->name.c_str() ) ); bounceItem( client, pItem, true ); return; } // Check if the user can grab the item if( !pChar->canPickUp( pItem ) ) { client->sysMessage( "You cannot pick that up." ); bounceItem( client, pItem, true ); return; } // The user can't see the item // Basically thats impossible as the client should deny moving the item // if it's not in line of sight but to prevent exploits if( !line_of_sight( client->socket(), pChar->pos, pItem->pos, TREES_BUSHES|WALLS_CHIMNEYS|DOORS|ROOFING_SLANTED|FLOORS_FLAT_ROOFING|LAVA_WATER ) ) { client->sysMessage( "You can't see the item." ); bounceItem( client, pItem, true ); return; } P_ITEM outmostCont = GetOutmostCont( pItem, 64 ); // If it's a trade-window, reset the ack-status if( outmostCont && ( outmostCont->contserial == pChar->serial ) && ( outmostCont->layer() == 0 ) && ( outmostCont->id() == 0x1E5E ) ) { // Get the other sides tradewindow P_ITEM tradeWindow = FindItemBySerial( calcserial( outmostCont->moreb1(), outmostCont->moreb2(), outmostCont->moreb3(), outmostCont->moreb4() ) ); // If one of the trade-windows has the ack-status reset it if( tradeWindow && ( tradeWindow->morez || outmostCont->morez ) ) { tradeWindow->morez = 0; outmostCont->morez = 0; sendtradestatus( tradeWindow, outmostCont ); } } // If the top-most container ( thats important ) is a corpse // and looting is a crime, flag the character criminal. if( outmostCont && outmostCont->corpse() ) { // For each item we take out we loose carma // if the corpse is innocent and not in our guild bool sameGuild = ( GuildCompare( pChar, FindCharBySerial( outmostCont->ownserial ) ) != 0 ); if( ( outmostCont->more2 == 1 ) && !pChar->Owns( outmostCont ) && !sameGuild ) { pChar->karma -= 5; criminal( pChar ); client->sysMessage( "You lost some karma." ); } } // Check if the item is too heavy //if( !pc_currchar->isGMorCounselor() ) //{ //} << Deactivated (DarkStorm) // ==== Grabbing the Item is allowed here ==== // Remove eventual item-bonusses if we're unequipping something if( pItem->layer() > 0 ) { P_CHAR wearer = FindCharBySerial( pItem->contserial ); if( wearer ) wearer->removeItemBonus( pItem ); } // Send the user a pickup sound if we're picking it up // From a container/paperdoll if( !pItem->isInWorld() ) soundeffect( client->socket(), 0x00, 0x57 ); // If we're picking up a specific amount of what we got // Take that into account if( pItem->amount() > 1 ) { UI32 pickedAmount = min( amount, pItem->amount() ); // We only have to split if we're not taking it all if( pickedAmount != pItem->amount() ) { P_ITEM splitItem = new cItem( *pItem ); // Create a new item to pick that up splitItem->SetSerial( cItemsManager::getInstance()->getUnusedSerial() ); splitItem->setAmount( pItem->amount() - pickedAmount ); splitItem->setContSerial( pItem->contserial ); splitItem->SetOwnSerial( pItem->ownserial ); splitItem->SetSpawnSerial( pItem->spawnserial ); // He needs to see the new item RefreshItem( splitItem ); // If we're taking something out of a spawn-region it's spawning "flag" is removed isn't it? pItem->SetSpawnSerial( INVALID_SERIAL ); pItem->setAmount( pickedAmount ); } } pItem->setContSerial( pChar->serial ); pItem->SetMultiSerial( INVALID_SERIAL ); pItem->setLayer( 0x1E ); // It's in the equipment of another character if( itemOwner && ( itemOwner != pChar ) ) { itemOwner->weight -= pItem->getWeight(); statwindow( calcSocketFromChar( itemOwner ), itemOwner ); } // If the item is in the bank or any sell-container it's NOT counted as char-weight bool inBank = ( outmostCont && ( outmostCont->contserial == pChar->serial ) && ( outmostCont->layer() >= 0x1A ) ); // Add the weight if: // - Picked from ground // - Picked out of another character // - Picked out of our bank or any other non-visible container if( ( itemOwner != pChar ) || !inBank ) { pChar->weight += pItem->getWeight(); statwindow( client->socket(), pChar ); } }
void cDragItems::dropOnChar( P_CLIENT client, P_ITEM pItem, P_CHAR pOtherChar ) { // Three possibilities: // If we're dropping it on ourself: packintobackpack // If we're dropping it on some other player: trade-window // If we're dropping it on some NPC: checkBehaviours // If not handeled: Equip the item if the NPC is owned by us P_CHAR pChar = client->player(); // Dropped on ourself if( pChar == pOtherChar ) { pItem->setLayer( 0 ); pItem->setContSerial( INVALID_SERIAL ); pItem->toBackpack( pChar ); return; } // Are we in range of our target if( !inrange1p( pChar, pOtherChar ) ) { client->sysMessage( "You are too far away from that character." ); bounceItem( client, pItem ); return; } // Can wee see our target if( !line_of_sight( client->socket(), pChar->pos, pOtherChar->pos, TREES_BUSHES|WALLS_CHIMNEYS|DOORS|ROOFING_SLANTED|FLOORS_FLAT_ROOFING|LAVA_WATER ) ) { client->sysMessage( "You can't see this character" ); bounceItem( client, pItem ); return; } // Open a secure trading window if( !pOtherChar->isNpc() && online( pOtherChar ) ) { // Check if we're already trading, // if not create a new window vector< SERIAL > equipment = contsp.getData( pChar->serial ); P_ITEM tradeWindow = NULL; for( UI16 i = 0; i < equipment.size(); i++ ) { P_ITEM pEquip = FindItemBySerial( equipment[ i ] ); // Is it a trade-window ? if( ( pEquip->layer() == 0 ) && ( pEquip->id() == 0x1E5E ) ) { P_ITEM tradeWindow = FindItemBySerial( calcserial( pEquip->moreb1(), pEquip->moreb2(), pEquip->moreb3(), pEquip->moreb4() ) ); if( tradeWindow && ( tradeWindow->contserial == pOtherChar->serial ) ) { tradeWindow = pEquip; break; } } } if( !tradeWindow ) tradeWindow = Trade->tradestart( client->socket(), pOtherChar ); pItem->setContSerial( tradeWindow->serial); pItem->pos.x = rand() % 60; pItem->pos.y = rand() % 60; pItem->pos.z = 9; pItem->setLayer( 0 ); SndRemoveitem( pItem->serial ); RefreshItem( pItem ); return; } // For our hirelings we have a special function if( pChar->Owns( pOtherChar ) ) { dropOnPet( client, pItem, pOtherChar ); return; } // Dropping based on AI Type switch( pOtherChar->npcaitype() ) { case 4: dropOnGuard( client, pItem, pOtherChar ); break; case 5: dropOnBeggar( client, pItem, pOtherChar ); break; case 8: dropOnBanker( client, pItem, pOtherChar ); break; case 19: dropOnBroker( client, pItem, pOtherChar ); break; }; // Try to train - works for any NPC if( pOtherChar->cantrain() ) if( pChar->trainer() == pOtherChar->serial ) dropOnTrainer( client, pItem, pOtherChar ); else pOtherChar->talk( "You need to tell me what you want to learn first" ); bounceItem( client, pItem ); return; }
void 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 } } } }