// Fires whenever a creature (NPC or PC) attacks another creature. If the creature is equipped with // a firearm, a particular animation is set and then the combat rules are fired. Provided all requirements are met, // the attacker plays the animation and may or may not hit his or her target. // Uses NWNX2 Events plugin. // Created by Quixsilver on Unknown Date // Modified by Zunath on May 24th, 2011 #include "adv_include" //#include "events_include" // Windows #include "cbt_atk_inc" #include "rwt_include" #include "nwnx_events" // Linux void main() { object oPC = OBJECT_SELF; //object oTarget = GetNWNXEventTarget( ); object oTarget = GetEventTarget(); // Added this check because I think NPCs are lagging the server. if(GetIsPC(oPC)) { // Check for sanctuary if this attack is PC versus PC if(GetIsPC(oTarget) && !GetIsDMPossessed(oTarget)) { // Either the attacker or target has sanctuary - prevent combat from happening if(RWT_GetDoesPlayerHaveSanctuary(oPC)) { FloatingTextStringOnCreature(ColorTokenRed() + "You are under the effects of PVP sanctuary and cannot engage in PVP. To disable this feature permanently refer to the 'Disable PVP Sanctuary' option in your rest menu." + ColorTokenEnd(), oPC, FALSE); AssignCommand(oPC, ClearAllActions()); return; } else if(RWT_GetDoesPlayerHaveSanctuary(oTarget)) { FloatingTextStringOnCreature(ColorTokenRed() + "Your target is under the effects of PVP sanctuary and cannot engage in PVP combat." + ColorTokenEnd(), oPC, FALSE); AssignCommand(oPC, ClearAllActions()); return; } } // PC is too busy to make an attack right now if(GetLocalInt(oPC, "RELOADING_GUN") || GetCurrentAction(oPC) == ACTION_SIT || GetLocalInt(oPC, "LOCKPICK_TEMPORARY_CURRENTLY_PICKING_LOCK")) { FloatingTextStringOnCreature(ColorTokenRed() + "You are too busy to attack right now.", oPC, FALSE); AssignCommand(oPC, ClearAllActions()); return; } // PC is dead or dying if(GetCurrentHitPoints(oPC) < 1) { AssignCommand(oPC, ClearAllActions()); return; } object oArea = GetArea(oPC); // Area is designated as "No PVP" if(GetIsPC(oTarget) && GetLocalInt(oArea, "NO_PVP") == TRUE) { AssignCommand(oPC, ClearAllActions()); FloatingTextStringOnCreature(ColorTokenRed() + "You cannot engage in PVP in this area." + ColorTokenEnd(), oPC, FALSE); return; } // Stop trying to attack a DM, dumbass if(GetIsDM(oTarget)) { AssignCommand(oPC, ClearAllActions()); return; } int bLineOfSight; // Determine which animation to use object oRightHand = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC); object oLeftHand = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC); struct GunInfoStruct stGun1Info = GUN_GetGunInfo(oRightHand); struct GunInfoStruct stGun2Info = GUN_GetGunInfo(oLeftHand); int iNumberOfShots = 1; int bUsingFirearm = FALSE; // All firearms must be marked to use the custom combat system if(stGun1Info.iGunType == GUN_TYPE_HANDGUN || stGun2Info.iGunType == GUN_TYPE_HANDGUN || stGun1Info.iGunType == GUN_TYPE_SMG || stGun2Info.iGunType == GUN_TYPE_SMG || stGun1Info.iGunType == GUN_TYPE_MAGNUM || stGun2Info.iGunType == GUN_TYPE_MAGNUM || stGun1Info.iGunType == GUN_TYPE_SHOTGUN ||stGun1Info.iGunType == GUN_TYPE_RIFLE || stGun1Info.iGunType == GUN_TYPE_ASSAULT_RIFLE) { // Disable sanctuary and other OnAreaEnter buffs effect eEffect = GetFirstEffect(oPC); while(GetIsEffectValid(eEffect)) { int iEffectType = GetEffectType(eEffect); if(iEffectType == EFFECT_TYPE_DAMAGE_REDUCTION || iEffectType == EFFECT_TYPE_SANCTUARY) { RemoveEffect(oPC, eEffect); } eEffect = GetNextEffect(oPC); } // Disable stealth mode if(GetActionMode(oPC, ACTION_MODE_STEALTH)) { SetActionMode(oPC, ACTION_MODE_STEALTH, FALSE); } bLineOfSight = LineOfSightObject(oPC, oTarget); // No line of sight and we're using the custom combat system. // Prevent from continuing. if(!bLineOfSight || GetLocalInt(oPC, "TEMP_DISABLE_FIRING")) { AssignCommand(oPC,ClearAllActions(TRUE)); return; } SetAttackAllowed(oPC, TRUE); bUsingFirearm = TRUE; } // Otherwise, the PC isn't using a firearm. Use the default combat system else { SetLocalInt(oPC, CBT_OVR_SVAR_ATTACK_ANIMATION, CBT_OVR_ANIMATION_NONE); SetAttackAllowed(oPC, FALSE); SetNumberShotsToFire(oPC, 0); } if(bUsingFirearm) { BypassEvent(); // Mode is determined by the right hand weapon. Figure out how many shots to fire based on mode if(GetLocalInt(oRightHand, "GUN_CUR_RATE_OF_FIRE") == 1) { iNumberOfShots = 3; } SetNumberShotsToFire(oPC, iNumberOfShots); float fDelay = 0.0; SetTarget(oPC, oTarget); if (bUsingFirearm && GetDistanceBetween(oPC, oTarget) > 1.0) { if (GetAttackAllowed(oPC)) { if (GetCommandable(oPC) && GetIsObjectValid(oTarget) && bLineOfSight) { AssignCommand(oPC,ClearAllActions(TRUE)); vector vDiff = GetPosition(oPC) - GetPosition(oTarget); float vAngle = fabs(VectorToAngle(vDiff) - GetFacing(oPC) - 180); if (vAngle > 1.0 && vAngle < 359.0) { TurnToFaceObject(oTarget, oPC); fDelay = 0.75; } // Quick players can sometimes get more than one cycle of shots off each attack. This should stop that. SetLocalInt(oPC, "TEMP_DISABLE_FIRING", TRUE); DelayCommand(fDelay, AssignCommand(oPC, MainAttack(oPC, oTarget))); DelayCommand(fDelay, DeleteLocalInt(oPC, "TEMP_DISABLE_FIRING")); } } } } } }