Code: | datablock GameBaseData(OneHandedAttackSwing) { seqName = "h1swing"; timeScale = 0.5; damageAmount = 30; //startDamage = 0.2; //endDamage = 0.6; startDamage = 0.2; endDamage = 1.3; };
datablock GameBaseData(OneHandedAttackSlice) { seqName = "h1slice"; timeScale = 0.5; damageAmount = 30; //startDamage = 0.3; //endDamage = 0.7; startDamage = 0.1; endDamage = 0.9; };
datablock GameBaseData(OneHandedAttackThrust) { seqName = "h1thrust"; timeScale = 0.5; damageAmount = 30; //startDamage = 0.4; //endDamage = 0.8; startDamage = 0.1; endDamage = 0.9; };
datablock GameBaseData(OneHandedJumpAttack) { seqName = "h1jumpattack"; timeScale = 1.0; damageAmount = 30; //startDamage = 0.4; //endDamage = 0.8; startDamage = 0.1; endDamage = 0.9; };
// this is the default function to call when firing a hand-to-hand weapon function WeaponImage::onFireHandToHand(%this, %obj, %slot) { if(%obj.hthStun) //|| %obj.shielded) return; // there was code here for special attacks %action = "Normal"; switch$(%action) { case "JumpAttack": %attack = %this.jumpAttack; case "Normal": // for now we randomly choose an attack %index = mFloor(getRandom()*(%this.hthNumAttacks-0.0001)); if (%index > (%this.hthNumAttacks-1)) %index = (%this.hthNumAttacks-1); %attack = %this.hthAttack[%index]; } // setup the "play once look anim" %obj.hthDamageAttack = %attack; %obj.hthDamageSeqPlaying = 1; %obj.hthDamageStartMS = $sim::Time; %obj.hthDamageLastId = -1;
if (!%obj.setArmThreadPlayOnce(%attack.seqName)) echo("ERROR in setArmThreadPlayOnce()"); return; }
// default weapon intersect function WeaponImage::onImageIntersect(%this,%player,%slot,%startvec,%endvec) { // if damage sequence is not playing then dont do damage if (!%player.hthDamageSeqPlaying || %player.getState() $= "Dead") return;
// determine if damage is active or if we can say the seq is done playing // based on current server time %offset = $sim::Time - %player.hthDamageStartMS;
// depending on which attack is playing... %attack = %player.hthDamageAttack; %startOffset = %attack.startDamage; %endOffset = %attack.endDamage;
// how long until the last damage is done // at which point we can say the seq has "Stopped playing" if (%offset > %endOffset) { %player.hthDamageSeqPlaying = 0; %player.hthDamageActive = 0; // echo("seq stopping (all damage done) %offset = " @ %offset); return; }
// how long it takes for damage to start...for now we just // have one interval and damage is active all during that interval if (%offset >%startOffset) %player.hthDamageActive = 1;
// no damage yet? if (!%player.hthDamageActive) { // echo("seq playing (no damage) %offset = " @ %offset); return; }
// search for just players to damage %searchMasks = $TypeMasks::PlayerObjectType | $TypeMasks::StaticShapeObjectType; // search for objects within the damage rays that fit the masks above %scanTarg = ContainerRayCast(%startvec, %endvec, %searchMasks, %slot);
//if(%scanTarg && (%scanTarg.getType() & $TypeMasks::PlayerObjectType)) // { // a target in range was found %target = firstWord(%scanTarg);
// store end point from raycast return buffer %pos = getWords(%scanTarg, 1, 3);
// if we have hit this person already...apply no more damage if (%target == %player.hthDamageLastId) return;
// save who we last damaged %player.hthDamageLastId = %target;
// Apply damage targetted object // Works for all shapebase objects. if (%target.getState() !$= "Dead" && %target.getId() !$= %player.getId()) { // shields and sword rebounding - JM The_Force if(%target.shielded) { %block = 1; // Now we see if we hit from behind... %forwardVec = %target.getEyeVector(); %objDir2D = getWord(%forwardVec, 0) @ " " @ getWord(%forwardVec,1) @ " " @ "0"; %objPos = %target.getPosition(); %dif = VectorSub(%objPos, %player.getPosition()); %dif = getWord(%dif, 0) @ " " @ getWord(%dif, 1) @ " 0"; %dif = VectorNormalize(%dif); %dot = VectorDot(%dif, %objDir2D); // 120 Deg angle test... // 1.05 == 60 degrees in radians if (%dot >= mCos(1.05)) %block = 0; } if(%block == 1) { //error("attack blocked!!"); //%player.playAudio(0,ShieldImpactSound); //makeSparks(%pos); stunPlayer(%player,%attack); pushPlayerBack(%player,%pos,%target,%attack); return; } %damage = %attack.damageAmount; %damageType = %this.item; // example: Axe / Sword etc
%damLoc = firstWord(%target.getDamageLocation(%pos)); // you can use this to add limited loacational damage, but the head is whats hit the most - TF //if(%damLoc $= "head") //error("object sliced on head"); //else if(%damLoc $= "torso") //error("object sliced on torso"); //else if(%damLoc $= "legs") //error("object sliced on legs");
// code ripped from Armor::damgae %target.applyDamage(%damage);
// this is in the Armor::damage //%location = "Body";
// Deal with client callbacks here because we don't have this // information in the onDamage or onDisable methods %client = %target.client; %sourceObject = %this; %sourceClient = %sourceObject ? %sourceObject.client : 0;
if (%target.getState() $= "Dead") { if(%client) { %client.onDeath(%sourceObject, %sourceClient, %damageType, %pos); $AlignmentCount[%player.client,%target.alliance] -= 2; } } else { $AlignmentCount[%player.client,%target.alliance] -= 0.2; stunPlayer(%target,%attack);
pushPlayerBack(%target,%pos,%player,%attack); } } }
// call when %victim is hit with %attack but does not die function stunPlayer(%vplayer, %attack) { // for now we stun every time...
// get the player for this object //if (!%victim.client || !%victim.client.player) if(!%vplayer.getType() & $TypeMasks::PlayerObjectType) { error("ATTEMPTING to STUN a non-player"); return; }
// if this player is in the middle of a hth swing themself, then // their swing is aborted. firstly we have to make sure they dont // do any damage, secondly we must blend their swing anim into // the stun anim if (%vplayer.hthDamageSeqPlaying) { // make sure they wont do damage.... %vplayer.hthDamageSeqPlaying = false;
// blend into the stun animation //error("STUN: victim: " @ %vplayer @ " DOING transition once..."); %vplayer.setArmThreadTransitionOnce("h1stun"); } else { // just start the stun animation //error("STUN: victim: " @ %vplayer @ " only doing a playonce..."); if(%vplayer.shielded)// not while stuned! %vplayer.setImageTrigger(1,false); %vplayer.setArmThreadPlayOnce("h1stun"); }
// the victim is now in a stun state //%vplayer.hthStunSequencePlaying = true; %vplayer.hthStun = true; schedule(1000, %vplayer, "resetStun", %vplayer); //%vplayer.hthStunStartMS = $sim::Time; }
function resetStun(%obj) { %obj.hthStun = false; }
function pushPlayerBack(%victim, %pos, %attacker, %attack) { // the push back is relative to the attacker // a straight push back would be along the attackers // Y axis....
// right now we always push the victim at his center // we could explore what happnes if we push at the // point of contact instead (might turn or do something intersting)
// get the usual direction to push...we could get the Y axis of // the attacker with getTransform() then grabbing the rotation part // and passing that to VectorOrthoBasis() and then using column 1 // whichi would be words 3,4,5 (couting from 0)...but that's overkill // for something that can be approximated pretty good by a line drawn // from attacker to victim...so let's use that instead %vpos = %victim.getWorldBoxCenter(); %pushDirection = VectorSub(%vpos,%attacker.getWorldBoxCenter()); %pushDirection = VectorNormalize(%pushDirection);
// hardoded impluse %impulse = 15.0;
// ok apply impulse to victim's center %mass = %victim.getDataBlock().mass; %pushVec = VectorScale(%pushDirection,%impulse * %mass);
//error("Applying, to player " @ %victim @ " of mass " @ %mass @ ", an impulseVec: " @ %pushVec);
%victim.applyImpulse(%vpos, %pushVec); }
function WeaponImage::onMount(%this,%obj,%slot) { // Images assume a false ammo state on load. We need to // set the state according to the current inventory. if (%obj.getInventory(%this.ammo)) %obj.setImageAmmo(%slot,true);
if (%this.customLookAnim !$= "") { %obj.setArmThread(%this.customLookAnim); } else { %obj.setArmThread("look"); } } |
Swords.
|