public Player targetClosestPC(Creature crt) { Player pc = null; int farDist = 99; foreach (Player p in mod.playerList) { if ((!p.charStatus.Equals("Dead")) && (p.hp >= 0) && (!p.steathModeOn)) { int dist = CalcDistance(crt.combatLocX, crt.combatLocY, p.combatLocX, p.combatLocY); if (dist == farDist) { //since at same distance, do a random check to see if switch or stay with current PC target if (gv.sf.RandInt(20) > 10) { //switch target pc = p; if (gv.mod.debugMode) { gv.cc.addLogText("<font color='yellow'>target:" + pc.name + "</font><BR>"); } } } else if (dist < farDist) { farDist = dist; pc = p; if (gv.mod.debugMode) { gv.cc.addLogText("<font color='yellow'>target:" + pc.name + "</font><BR>"); } } } } return pc; }
public Coordinate targetBestPointLocation(Creature crt) { Coordinate targetLoc = new Coordinate(-1,-1); //JamesManhattan Utility maximization function for the VERY INTELLIGENT CREATURE CASTER int utility = 0; //utility int optimalUtil = 0; //optimal utility, a storage of the highest achieved Coordinate selectedPoint = new Coordinate(crt.combatLocX, crt.combatLocY); //Initial Select Point is Creature itself, then loop through all squares within range! for (int y = gv.sf.SpellToCast.range; y > -gv.sf.SpellToCast.range; y--) //start at far range and work backwards does a pretty good job of avoiding hitting allies. { for (int x = gv.sf.SpellToCast.range; x > -gv.sf.SpellToCast.range; x--) { utility = 0; //reset utility for each point tested selectedPoint = new Coordinate(crt.combatLocX + x, crt.combatLocY + y); //check if selected point is a valid location on combat map if ((selectedPoint.X < 0) || (selectedPoint.X > 6) || (selectedPoint.Y < 0) || (selectedPoint.Y > 6)) { continue; } //check if selected point is in LoS, if not skip this point int endX = selectedPoint.X * gv.squareSize + (gv.squareSize / 2); int endY = selectedPoint.Y * gv.squareSize + (gv.squareSize / 2); int startX = crt.combatLocX * gv.squareSize + (gv.squareSize / 2); int startY = crt.combatLocY * gv.squareSize + (gv.squareSize / 2); if (!isVisibleLineOfSight(new Coordinate(endX, endY), new Coordinate(startX, startY))) { continue; } if (selectedPoint == new Coordinate(crt.combatLocX, crt.combatLocY)) { utility -= 4; //the creature at least attempts to avoid hurting itself, but if surrounded might fireball itself! if (crt.hp <= crt.hpMax / 4) //caster is wounded, definately avoids itself. { utility -= 4; } } foreach (Creature crtr in mod.currentEncounter.encounterCreatureList) //if its allies are in the burst subtract a point, or half depending on how evil it is. { if (this.CalcDistance(crtr.combatLocX, crtr.combatLocY, selectedPoint.X, selectedPoint.Y) <= gv.sf.SpellToCast.aoeRadius) //if friendly creatures are in the AOE burst, count how many, subtract 0.5 for each, evil is evil { utility -= 1; } } foreach (Player tgt_pc in mod.playerList) { if ((this.CalcDistance(tgt_pc.combatLocX, tgt_pc.combatLocY, selectedPoint.X, selectedPoint.Y) <= gv.sf.SpellToCast.aoeRadius) && (tgt_pc.hp > 0)) //if players are in the AOE burst, count how many, total count is utility //&& sf.GetLocalInt(tgt_pc.Tag, "StealthModeOn") != 1 <-throws an annoying message if not found!! { utility += 2; if (utility > optimalUtil) { //optimal found, choose this point optimalUtil = utility; targetLoc = selectedPoint; } } } if (gv.mod.debugMode) { gv.cc.addLogText("<font color='yellow'>(" + selectedPoint.X + "," + selectedPoint.Y + "):" + utility + "</font><BR>"); } } } return targetLoc; }
public void TargetCast(Player pc) { int endX = targetHighlightCenterLocation.X * gv.squareSize + (gv.squareSize / 2); int endY = targetHighlightCenterLocation.Y * gv.squareSize + (gv.squareSize / 2); int startX = pc.combatLocX * gv.squareSize + (gv.squareSize / 2); int startY = pc.combatLocY * gv.squareSize + (gv.squareSize / 2); if ((isValidCastTarget(pc)) && (isVisibleLineOfSight(new Coordinate(endX, endY), new Coordinate(startX, startY)))) { if ((targetHighlightCenterLocation.X < pc.combatLocX) && (!pc.combatFacingLeft)) //attack left { pc.token = gv.cc.flip(pc.token); pc.combatFacingLeft = true; } else if ((targetHighlightCenterLocation.X > pc.combatLocX) && (pc.combatFacingLeft)) //attack right { pc.token = gv.cc.flip(pc.token); pc.combatFacingLeft = false; } //doCombatCast(pc); gv.touchEnabled = false; creatureToAnimate = null; playerToAnimate = pc; gv.Invalidate(); animationState = AnimationState.PcCastAttackAnimation; gv.postDelayed("doAnimation", 5 * mod.combatAnimationSpeed); } }
public void doOnHitScriptBasedOnFilename(string filename, Creature crt, Player pc) { if (!filename.Equals("none")) { try { if (filename.Equals("onHitBeetleFire.cs")) { float resist = (float)(1f - ((float)pc.damageTypeResistanceTotalFire / 100f)); float damage = (1 * gv.sf.RandInt(2)) + 0; int fireDam = (int)(damage * resist); if (gv.mod.debugMode) { addLogText("<font color='yellow'>" + "resist = " + resist + " damage = " + damage + " fireDam = " + fireDam + "</font>" + "<BR>"); } addLogText("<font color='aqua'>" + pc.name + "</font>" + "<font color='white'>" + " is burned for " + "</font>" + "<font color='red'>" + fireDam + "</font>" + "<font color='white'>" + " hit point(s)" + "</font>" + "<BR>"); pc.hp -= fireDam; } else if (filename.Equals("onHitOneFire.cs")) { float resist = (float)(1f - ((float)crt.damageTypeResistanceValueFire / 100f)); float damage = 1.0f; int fireDam = (int)(damage * resist); if (gv.mod.debugMode) { addLogText("<font color='yellow'>" + "resist = " + resist + " damage = " + damage + " fireDam = " + fireDam + "</font>" + "<BR>"); } addLogText("<font color='aqua'>" + crt.cr_name + "</font>" + "<font color='white'>" + " is burned for " + "</font>" + "<font color='red'>" + fireDam + "</font>" + "<font color='white'>" + " hit point(s)" + "</font>" + "<BR>"); crt.hp -= fireDam; } else if (filename.Equals("onHitOneTwoFire.cs")) { float resist = (float)(1f - ((float)crt.damageTypeResistanceValueFire / 100f)); float damage = (1 * gv.sf.RandInt(2)) + 0; int fireDam = (int)(damage * resist); if (gv.mod.debugMode) { addLogText("<font color='yellow'>" + "resist = " + resist + " damage = " + damage + " fireDam = " + fireDam + "</font>" + "<BR>"); } addLogText("<font color='aqua'>" + crt.cr_name + "</font>" + "<font color='white'>" + " is burned for " + "</font>" + "<font color='red'>" + fireDam + "</font>" + "<font color='white'>" + " hit point(s)" + "</font>" + "<BR>"); crt.hp -= fireDam; } else if (filename.Equals("onHitTwoThreeFire.cs")) { float resist = (float)(1f - ((float)crt.damageTypeResistanceValueFire / 100f)); float damage = (1 * gv.sf.RandInt(2)) + 1; int fireDam = (int)(damage * resist); if (gv.mod.debugMode) { addLogText("<font color='yellow'>" + "resist = " + resist + " damage = " + damage + " fireDam = " + fireDam + "</font>" + "<BR>"); } addLogText("<font color='aqua'>" + crt.cr_name + "</font>" + "<font color='white'>" + " is burned for " + "</font>" + "<font color='red'>" + fireDam + "</font>" + "<font color='white'>" + " hit point(s)" + "</font>" + "<BR>"); crt.hp -= fireDam; } else if (filename.Equals("onHitPcPoisonedLight.cs")) { int saveChkRoll = gv.sf.RandInt(20); int saveChk = saveChkRoll + pc.reflex; int DC = 13; if (saveChk >= DC) //passed save check { addLogText("<font color='yellow'>" + pc.name + " avoids being poisoned" + "</font>" + "<BR>"); if (gv.mod.debugMode) { addLogText("<font color='yellow'>" + saveChkRoll + " + " + pc.reflex + " >= " + DC + "</font>" + "<BR>"); } } else //failed check { addLogText("<font color='red'>" + pc.name + " is poisoned" + "</font>" + "<BR>"); Effect ef = gv.mod.getEffectByTag("poisonedLight"); pc.AddEffectByObject(ef, gv.mod.WorldTime); } } else if (filename.Equals("onHitPcPoisonedMedium.cs")) { int saveChkRoll = gv.sf.RandInt(20); int saveChk = saveChkRoll + pc.reflex; int DC = 16; if (saveChk >= DC) //passed save check { addLogText("<font color='yellow'>" + pc.name + " avoids being poisoned" + "</font>" + "<BR>"); if (gv.mod.debugMode) { addLogText("<font color='yellow'>" + saveChkRoll + " + " + pc.reflex + " >= " + DC + "</font>" + "<BR>"); } } else //failed check { addLogText("<font color='red'>" + pc.name + " is poisoned" + "</font>" + "<BR>"); Effect ef = gv.mod.getEffectByTag("poisonedMedium"); pc.AddEffectByObject(ef, gv.mod.WorldTime); } } } catch (Exception ex) { //IBMessageBox.Show(game, "failed to run script"); } } }
public void BasicAttacker(Creature crt) { Player pc = targetClosestPC(crt); gv.sf.CombatTarget = pc; gv.sf.ActionToTake = "Attack"; }
public int doActualCombatAttack(Player pc, Creature crt, int attackNumber) { //always decrement ammo by one whether a hit or miss this.decrementAmmo(pc); int attackRoll = gv.sf.RandInt(20); int attackMod = CalcPcAttackModifier(pc); int attack = attackRoll + attackMod; int defense = CalcCreatureDefense(crt); int damage = CalcPcDamageToCreature(pc, crt); //natural 20 always hits if ((attack >= defense) || (attackRoll == 20)) //HIT { crt.hp = crt.hp - damage; gv.cc.addLogText("<font color='aqua'>" + pc.name + "</font>" + "<font color='white'>" + " attacks " + "</font>" + "<font color='silver'>" + crt.cr_name + "</font>" + "<BR>"); gv.cc.addLogText("<font color='white'>" + " and HITS (" + "</font>" + "<font color='lime'>" + damage + "</font>" + "<font color='white'>" + " damage)" + "</font>" + "<BR>"); gv.cc.addLogText("<font color='white'>" + attackRoll + " + " + attackMod + " >= " + defense + "</font>" + "<BR>"); //#region onScoringHit script of creature doOnHitScriptBasedOnFilename(mod.getItemByResRefForInfo(pc.MainHandRefs.resref).onScoringHit, crt, pc); //#endregion Item it = mod.getItemByResRefForInfo(pc.AmmoRefs.resref); if (it != null) { doOnHitScriptBasedOnFilename(mod.getItemByResRefForInfo(pc.AmmoRefs.resref).onScoringHit, crt, pc); } //play attack sound for melee (not ranged) if (mod.getItemByResRefForInfo(pc.MainHandRefs.resref).category.Equals("Melee")) { gv.PlaySound(mod.getItemByResRefForInfo(pc.MainHandRefs.resref).itemOnUseSound); } //Draw floaty text showing damage above PC int txtH = (int)gv.drawFontReg.Height; int shiftUp = 0 - (attackNumber * txtH); floatyTextOn = true; gv.cc.addFloatyText(new Coordinate(crt.combatLocX, crt.combatLocY), damage + "", shiftUp); gv.postDelayed("doFloatyText", 100); if (crt.hp <= 0) { gv.cc.addLogText("<font color='lime'>You killed the " + crt.cr_name + "</font><BR>"); try { for (int x = mod.currentEncounter.encounterCreatureList.Count - 1; x >= 0; x--) { if (mod.currentEncounter.encounterCreatureList[x] == crt) { try { //do OnDeath LOGIC TREE gv.cc.doLogicTreeBasedOnTag(crt.onDeathLogicTree, crt.onDeathParms); mod.currentEncounter.encounterCreatureList.RemoveAt(x); mod.currentEncounter.encounterCreatureRefsList.RemoveAt(x); } catch (Exception e) { //e.printStackTrace(); } } } //mod.currentEncounter.encounterCreatureList.remove(crt); } catch (Exception e) { //e.printStackTrace(); } return 2; //killed } else { return 1; //hit } } else //MISSED { //play attack sound for melee (not ranged) if (mod.getItemByResRefForInfo(pc.MainHandRefs.resref).category.Equals("Melee")) { gv.PlaySound(mod.getItemByResRefForInfo(pc.MainHandRefs.resref).itemOnUseSound); } gv.cc.addLogText("<font color='aqua'>" + pc.name + "</font>" + "<font color='white'>" + " attacks " + "</font>" + "<font color='gray'>" + crt.cr_name + "</font>" + "<BR>"); gv.cc.addLogText("<font color='white'>" + " and MISSES" + "</font>" + "<BR>"); gv.cc.addLogText("<font color='white'>" + attackRoll + " + " + attackMod + " < " + defense + "</font>" + "<BR>"); return 0; //missed } }
public void doAnimationController() { if (animationState == AnimationState.None) { return; } else if (animationState == AnimationState.PcMeleeAttackAnimation) { creatureToAnimate = null; playerToAnimate = null; gv.Invalidate(); Player pc = mod.playerList[currentPlayerIndex]; doCombatAttack(pc); } else if (animationState == AnimationState.CreatureHitAnimation) { drawHitAnimation = false; hitAnimationLocation = new Coordinate(); gv.Invalidate(); //check for end of encounter checkEndEncounter(); //end PC's turn gv.touchEnabled = true; animationState = AnimationState.None; endPcTurn(true); } else if (animationState == AnimationState.CreatureMissedAnimation) { drawMissAnimation = false; hitAnimationLocation = new Coordinate(); gv.Invalidate(); //check for end of encounter checkEndEncounter(); gv.touchEnabled = true; animationState = AnimationState.None; //end PC's turn endPcTurn(true); } else if (animationState == AnimationState.CreatureMeleeAttackAnimation) { creatureToAnimate = null; playerToAnimate = null; gv.Invalidate(); doStandardCreatureAttack(); } else if (animationState == AnimationState.PcHitAnimation) { drawHitAnimation = false; hitAnimationLocation = new Coordinate(); gv.Invalidate(); animationState = AnimationState.None; endCreatureTurn(); } else if (animationState == AnimationState.PcMissedAnimation) { drawMissAnimation = false; hitAnimationLocation = new Coordinate(); gv.Invalidate(); animationState = AnimationState.None; endCreatureTurn(); } else if (animationState == AnimationState.PcRangedAttackAnimation) { creatureToAnimate = null; playerToAnimate = null; gv.Invalidate(); Player pc = mod.playerList[currentPlayerIndex]; //do projectile next drawProjectileAnimation = true; projectileAnimationLocation = new Coordinate(pc.combatLocX * gv.squareSize, pc.combatLocY * gv.squareSize); //load projectile image projectile = gv.cc.LoadBitmap(mod.getItemByResRefForInfo(pc.AmmoRefs.resref).projectileSpriteFilename); if (pc.combatLocY < targetHighlightCenterLocation.Y) { projectile = gv.cc.FlipHorz(projectile); } //reset animation frame counter animationFrameIndex = 0; gv.Invalidate(); animationState = AnimationState.PcRangedProjectileAnimation; gv.postDelayed("doAnimation", 2 * mod.combatAnimationSpeed); } else if (animationState == AnimationState.PcRangedProjectileAnimation) { Player pc = mod.playerList[currentPlayerIndex]; //if at target, do ending if ((projectileAnimationLocation.X == targetHighlightCenterLocation.X * gv.squareSize) && (projectileAnimationLocation.Y == targetHighlightCenterLocation.Y * gv.squareSize)) { drawProjectileAnimation = false; projectileAnimationLocation = new Coordinate(); drawEndingAnimation = true; endingAnimationLocation = new Coordinate(targetHighlightCenterLocation.X * gv.squareSize, targetHighlightCenterLocation.Y * gv.squareSize); animationFrameIndex = 0; ending_fx = gv.cc.LoadBitmap(mod.getItemByResRefForInfo(pc.AmmoRefs.resref).spriteEndingFilename); gv.Invalidate(); animationState = AnimationState.PcRangedEndingAnimation; gv.postDelayed("doAnimation", 2 * mod.combatAnimationSpeed); } else //if not at target, get new coordinate and keep going { //if frame is last, reset animationFrameIndex++; if (animationFrameIndex > 4) {animationFrameIndex = 0;} //get next coordinate projectileAnimationLocation = GetNextProjectileCoordinate(new Coordinate(pc.combatLocX, pc.combatLocY), targetHighlightCenterLocation); gv.Invalidate(); animationState = AnimationState.PcRangedProjectileAnimation; gv.postDelayed("doAnimation", 2 * mod.combatAnimationSpeed); } } else if (animationState == AnimationState.PcRangedEndingAnimation) { Player pc = mod.playerList[currentPlayerIndex]; if ((animationFrameIndex < 3) && (!mod.getItemByResRefForInfo(pc.MainHandRefs.resref).spriteEndingFilename.Equals("none"))) { animationFrameIndex++; gv.Invalidate(); animationState = AnimationState.PcRangedEndingAnimation; gv.postDelayed("doAnimation", 2 * mod.combatAnimationSpeed); } else //if not at target, get new coordinate and keep going { drawEndingAnimation = false; endingAnimationLocation = new Coordinate(); animationFrameIndex = 0; //loop through 4 times gv.Invalidate(); animationState = AnimationState.None; gv.touchEnabled = true; //Player pc = mod.playerList.get(currentPlayerIndex); doCombatAttack(pc); } } else if (animationState == AnimationState.PcCastAttackAnimation) { creatureToAnimate = null; playerToAnimate = null; gv.Invalidate(); Player pc = mod.playerList[currentPlayerIndex]; //do projectile next drawProjectileAnimation = true; projectileAnimationLocation = new Coordinate(pc.combatLocX * gv.squareSize, pc.combatLocY * gv.squareSize); //load projectile image projectile = gv.cc.LoadBitmap(gv.cc.currentSelectedSpell.spriteFilename); if (pc.combatLocY < targetHighlightCenterLocation.Y) { projectile = gv.cc.FlipHorz(projectile); } //reset animation frame counter animationFrameIndex = 0; gv.Invalidate(); animationState = AnimationState.PcCastProjectileAnimation; gv.postDelayed("doAnimation", 2 * mod.combatAnimationSpeed); //play cast projectile sound gv.PlaySound(gv.cc.currentSelectedSpell.spellStartSound); } else if (animationState == AnimationState.PcCastProjectileAnimation) { Player pc = mod.playerList[currentPlayerIndex]; //if at target, do ending if ((projectileAnimationLocation.X == targetHighlightCenterLocation.X * gv.squareSize) && (projectileAnimationLocation.Y == targetHighlightCenterLocation.Y * gv.squareSize)) { drawProjectileAnimation = false; projectileAnimationLocation = new Coordinate(); drawEndingAnimation = true; endingAnimationLocation = new Coordinate(targetHighlightCenterLocation.X * gv.squareSize, targetHighlightCenterLocation.Y * gv.squareSize); animationFrameIndex = 0; ending_fx = gv.cc.LoadBitmap(gv.cc.currentSelectedSpell.spriteEndingFilename); gv.Invalidate(); animationState = AnimationState.PcCastEndingAnimation; gv.postDelayed("doAnimation", 2 * mod.combatAnimationSpeed); //play cast ending sound gv.PlaySound(gv.cc.currentSelectedSpell.spellEndSound); } else //if not at target, get new coordinate and keep going { //if frame is last, reset animationFrameIndex++; if (animationFrameIndex > 4) {animationFrameIndex = 0;} //get next coordinate projectileAnimationLocation = GetNextProjectileCoordinate(new Coordinate(pc.combatLocX, pc.combatLocY), targetHighlightCenterLocation); gv.Invalidate(); animationState = AnimationState.PcCastProjectileAnimation; gv.postDelayed("doAnimation", 2 * mod.combatAnimationSpeed); } } else if (animationState == AnimationState.PcCastEndingAnimation) { if (animationFrameIndex < 3) { animationFrameIndex++; gv.Invalidate(); animationState = AnimationState.PcCastEndingAnimation; gv.postDelayed("doAnimation", 2 * mod.combatAnimationSpeed); } else //if not at target, get new coordinate and keep going { drawEndingAnimation = false; endingAnimationLocation = new Coordinate(); animationFrameIndex = 0; //loop through 4 times gv.Invalidate(); animationState = AnimationState.None; gv.touchEnabled = true; Player pc = mod.playerList[currentPlayerIndex]; doCombatCast(pc); } } else if (animationState == AnimationState.CreatureRangedAttackAnimation) { creatureToAnimate = null; playerToAnimate = null; gv.Invalidate(); Creature crt = mod.currentEncounter.encounterCreatureList[creatureIndex]; //do projectile next drawProjectileAnimation = true; projectileAnimationLocation = new Coordinate(crt.combatLocX * gv.squareSize, crt.combatLocY * gv.squareSize); //load projectile image projectile = gv.cc.LoadBitmap(crt.cr_projSpriteFilename); if (crt.combatLocY < creatureTargetLocation.Y) { projectile = gv.cc.FlipHorz(projectile); } //reset animation frame counter animationFrameIndex = 0; gv.Invalidate(); animationState = AnimationState.CreatureRangedProjectileAnimation; gv.postDelayed("doAnimation", 2 * mod.combatAnimationSpeed); } else if (animationState == AnimationState.CreatureRangedProjectileAnimation) { Creature crt = mod.currentEncounter.encounterCreatureList[creatureIndex]; //if at target, do ending if ((projectileAnimationLocation.X == creatureTargetLocation.X * gv.squareSize) && (projectileAnimationLocation.Y == creatureTargetLocation.Y * gv.squareSize)) { drawProjectileAnimation = false; projectileAnimationLocation = new Coordinate(); drawEndingAnimation = true; endingAnimationLocation = new Coordinate(creatureTargetLocation.X * gv.squareSize, creatureTargetLocation.Y * gv.squareSize); animationFrameIndex = 0; ending_fx = gv.cc.LoadBitmap(crt.cr_spriteEndingFilename); gv.Invalidate(); animationState = AnimationState.CreatureRangedEndingAnimation; gv.postDelayed("doAnimation", 2 * mod.combatAnimationSpeed); } else //if not at target, get new coordinate and keep going { //if frame is last, reset animationFrameIndex++; if (animationFrameIndex > 4) {animationFrameIndex = 0;} //get next coordinate projectileAnimationLocation = GetNextProjectileCoordinate(new Coordinate(crt.combatLocX, crt.combatLocY), creatureTargetLocation); gv.Invalidate(); animationState = AnimationState.CreatureRangedProjectileAnimation; gv.postDelayed("doAnimation", 2 * mod.combatAnimationSpeed); } } else if (animationState == AnimationState.CreatureRangedEndingAnimation) { Creature crt = mod.currentEncounter.encounterCreatureList[creatureIndex]; if ((animationFrameIndex < 3) && (!crt.cr_spriteEndingFilename.Equals("none"))) { animationFrameIndex++; gv.Invalidate(); animationState = AnimationState.CreatureRangedEndingAnimation; gv.postDelayed("doAnimation", 2 * mod.combatAnimationSpeed); } else //if not at target, get new coordinate and keep going { drawEndingAnimation = false; endingAnimationLocation = new Coordinate(); animationFrameIndex = 0; //loop through 4 times gv.Invalidate(); animationState = AnimationState.None; //touchEnabled = true; doStandardCreatureAttack(); } } else if (animationState == AnimationState.CreatureCastAttackAnimation) { creatureToAnimate = null; playerToAnimate = null; gv.Invalidate(); Creature crt = mod.currentEncounter.encounterCreatureList[creatureIndex]; //do projectile next drawProjectileAnimation = true; projectileAnimationLocation = new Coordinate(crt.combatLocX * gv.squareSize, crt.combatLocY * gv.squareSize); //load projectile image projectile = gv.cc.LoadBitmap(gv.sf.SpellToCast.spriteFilename); if (crt.combatLocY < creatureTargetLocation.Y) { projectile = gv.cc.FlipHorz(projectile); } //reset animation frame counter animationFrameIndex = 0; gv.Invalidate(); animationState = AnimationState.CreatureCastProjectileAnimation; gv.postDelayed("doAnimation", 2 * mod.combatAnimationSpeed); //play cast start sound gv.PlaySound(gv.sf.SpellToCast.spellStartSound); } else if (animationState == AnimationState.CreatureCastProjectileAnimation) { Creature crt = mod.currentEncounter.encounterCreatureList[creatureIndex]; //if at target, do ending if ((projectileAnimationLocation.X == creatureTargetLocation.X * gv.squareSize) && (projectileAnimationLocation.Y == creatureTargetLocation.Y * gv.squareSize)) { drawProjectileAnimation = false; projectileAnimationLocation = new Coordinate(); drawEndingAnimation = true; endingAnimationLocation = new Coordinate(creatureTargetLocation.X * gv.squareSize, creatureTargetLocation.Y * gv.squareSize); animationFrameIndex = 0; ending_fx = gv.cc.LoadBitmap(gv.sf.SpellToCast.spriteEndingFilename); gv.Invalidate(); animationState = AnimationState.CreatureCastEndingAnimation; gv.postDelayed("doAnimation", 2 * mod.combatAnimationSpeed); //play cast ending sound gv.PlaySound(gv.sf.SpellToCast.spellEndSound); } else //if not at target, get new coordinate and keep going { //if frame is last, reset animationFrameIndex++; if (animationFrameIndex > 4) {animationFrameIndex = 0;} //get next coordinate projectileAnimationLocation = GetNextProjectileCoordinate(new Coordinate(crt.combatLocX, crt.combatLocY), creatureTargetLocation); gv.Invalidate(); animationState = AnimationState.CreatureCastProjectileAnimation; gv.postDelayed("doAnimation", 2 * mod.combatAnimationSpeed); } } else if (animationState == AnimationState.CreatureCastEndingAnimation) { if (animationFrameIndex < 3) { animationFrameIndex++; gv.Invalidate(); animationState = AnimationState.CreatureCastEndingAnimation; gv.postDelayed("doAnimation", 2 * mod.combatAnimationSpeed); } else //if not at target, get new coordinate and keep going { drawEndingAnimation = false; endingAnimationLocation = new Coordinate(); animationFrameIndex = 0; //loop through 4 times gv.Invalidate(); animationState = AnimationState.None; //touchEnabled = true; doCreatureSpell(); } } else if (animationState == AnimationState.CreatureThink) { creatureToAnimate = null; playerToAnimate = null; gv.Invalidate(); doCreatureTurnAfterDelay(); } else if (animationState == AnimationState.CreatureMove) { creatureToAnimate = null; playerToAnimate = null; gv.Invalidate(); Creature crt = mod.currentEncounter.encounterCreatureList[creatureIndex]; CreatureDoesAttack(crt); //endCreatureTurn(); } }
public int CalcCreatureDefense(Creature crt) { int defense = crt.AC; if (crt.cr_status.Equals("Held")) { defense -= 4; gv.cc.addFloatyText(new Coordinate(crt.combatLocX, crt.combatLocY), "+4 att", "green"); } return defense; }
public void GeneralCaster(Creature crt) { gv.sf.SpellToCast = null; //just pick a random spell from KnownSpells //try a few times to pick a random spell that has enough SP for (int i = 0; i < 10; i++) { int rnd = gv.sf.RandInt(crt.knownSpellsTags.Count); Spell sp = mod.getSpellByTag(crt.knownSpellsTags[rnd-1]); if (sp != null) { /*if (sf.frm.debugMode) { c.logText("KnownSpell: " + sp.SpellName, Color.Black); c.logText(Environment.NewLine, Color.Black); }*/ if (sp.costSP <= crt.sp) { gv.sf.SpellToCast = sp; /*if (sf.frm.debugMode) { c.logText("SpellToCast: " + sf.SpellToCast.SpellName, Color.Black); c.logText(Environment.NewLine, Color.Black); }*/ if (gv.sf.SpellToCast.spellTargetType.Equals("Enemy")) { Player pc = targetClosestPC(crt); gv.sf.CombatTarget = pc; gv.sf.ActionToTake = "Cast"; break; } else if (gv.sf.SpellToCast.spellTargetType.Equals("PointLocation")) { //Player pc = targetClosestPC(crt); //gv.sf.CombatTarget = new Coordinate(pc.combatLocX, pc.combatLocY); //we are using a Coordinate type because the selected spell is looking for a Coordinate type (square location) Coordinate bestLoc = targetBestPointLocation(crt); if (bestLoc == new Coordinate(-1,-1)) { //didn't find a target so use closest PC Player pc = targetClosestPC(crt); gv.sf.CombatTarget = new Coordinate(pc.combatLocX, pc.combatLocY); } else { gv.sf.CombatTarget = targetBestPointLocation(crt); } gv.sf.ActionToTake = "Cast"; break; } else if (gv.sf.SpellToCast.spellTargetType.Equals("Friend")) { //target is another creature (currently assumed that spell is a heal spell) Creature targetCrt = GetCreatureWithMostDamaged(); if (targetCrt != null) { gv.sf.CombatTarget = targetCrt; gv.sf.ActionToTake = "Cast"; break; } else //didn't find a target that needs HP { gv.sf.SpellToCast = null; continue; } } else if (gv.sf.SpellToCast.spellTargetType.Equals("Self")) { //target is self (currently assumed that spell is a heal spell) Creature targetCrt = crt; if (targetCrt != null) { gv.sf.CombatTarget = targetCrt; gv.sf.ActionToTake = "Cast"; break; } } else //didn't find a target so set to null so that will use attack instead { gv.sf.SpellToCast = null; } } } } if (gv.sf.SpellToCast == null) //didn't find a spell that matched the criteria so use attack instead { Player pc = targetClosestPC(crt); gv.sf.CombatTarget = pc; gv.sf.ActionToTake = "Attack"; } }
public void doOnHitScriptBasedOnFilename(String filename, Creature crt, Player pc) { if (!filename.Equals("none")) { try { if (filename.Equals("onHitBeetleFire.cs")) { float resist = (float)(1f - ((float)pc.damageTypeResistanceTotalFire / 100f)); float damage = (1 * gv.sf.RandInt(2)) + 0; int fireDam = (int)(damage * resist); if (mod.debugMode) { gv.cc.addLogText("<font color='yellow'>" + "resist = " + resist + " damage = " + damage + " fireDam = " + fireDam + "</font>" + "<BR>"); } gv.cc.addLogText("<font color='aqua'>" + pc.name + "</font>" + "<font color='white'>" + " is burned for " + "</font>" + "<font color='red'>" + fireDam + "</font>" + "<font color='white'>" + " hit point(s)" + "</font>" + "<BR>"); pc.hp -= fireDam; } else if (filename.Equals("onHitMaceOfStunning.cs")) { int tryHold = gv.sf.RandInt(100); if (tryHold > 50) { //attempt to hold PC int saveChkRoll = gv.sf.RandInt(20); int saveChk = saveChkRoll + crt.fortitude; int DC = 15; if (saveChk >= DC) //passed save check { gv.cc.addLogText("<font color='yellow'>" + crt.cr_name + " avoids stun (" + saveChkRoll + " + " + crt.fortitude + " >= " + DC + ")</font><BR>"); } else { gv.cc.addLogText("<font color='red'>" + crt.cr_name + " is stunned by mace (" + saveChkRoll + " + " + crt.fortitude + " < " + DC + ")</font><BR>"); crt.cr_status = "Held"; Effect ef = mod.getEffectByTag("hold"); crt.AddEffectByObject(ef, mod.WorldTime); } } } else if (filename.Equals("onHitBeetleAcid.cs")) { float resist = (float)(1f - ((float)pc.damageTypeResistanceTotalAcid / 100f)); float damage = (1 * gv.sf.RandInt(2)) + 0; int acidDam = (int)(damage * resist); if (mod.debugMode) { gv.cc.addLogText("<font color='yellow'>" + "resist = " + resist + " damage = " + damage + " acidDam = " + acidDam + "</font>" + "<BR>"); } gv.cc.addLogText("<font color='aqua'>" + pc.name + "</font>" + "<font color='white'>" + " is burned for " + "</font>" + "<font color='lime'>" + acidDam + "</font>" + "<font color='white'>" + " hit point(s)" + "</font>" + "<BR>"); pc.hp -= acidDam; //attempt to hold PC int saveChkRoll = gv.sf.RandInt(20); //int saveChk = saveChkRoll + target.Will; int saveChk = saveChkRoll + pc.fortitude; int DC = 10; if (saveChk >= DC) //passed save check { gv.cc.addLogText("<font color='yellow'>" + pc.name + " avoids the acid stun (" + saveChkRoll + " + " + pc.fortitude + " >= " + DC + ")</font><BR>"); } else { gv.cc.addLogText("<font color='red'>" + pc.name + " is held by an acid stun (" + saveChkRoll + " + " + pc.fortitude + " < " + DC + ")</font><BR>"); pc.charStatus = "Held"; Effect ef = mod.getEffectByTag("hold"); pc.AddEffectByObject(ef, mod.WorldTime); } } else if (filename.Equals("onHitOneFire.cs")) { float resist = (float)(1f - ((float)crt.damageTypeResistanceValueFire / 100f)); float damage = 1.0f; int fireDam = (int)(damage * resist); if (mod.debugMode) { gv.cc.addLogText("<font color='yellow'>" + "resist = " + resist + " damage = " + damage + " fireDam = " + fireDam + "</font>" + "<BR>"); } gv.cc.addLogText("<font color='aqua'>" + crt.cr_name + "</font>" + "<font color='white'>" + " is burned for " + "</font>" + "<font color='red'>" + fireDam + "</font>" + "<font color='white'>" + " hit point(s)" + "</font>" + "<BR>"); crt.hp -= fireDam; } else if (filename.Equals("onHitOneTwoFire.cs")) { float resist = (float)(1f - ((float)crt.damageTypeResistanceValueFire / 100f)); float damage = (1 * gv.sf.RandInt(2)) + 0; int fireDam = (int)(damage * resist); if (mod.debugMode) { gv.cc.addLogText("<font color='yellow'>" + "resist = " + resist + " damage = " + damage + " fireDam = " + fireDam + "</font>" + "<BR>"); } gv.cc.addLogText("<font color='aqua'>" + crt.cr_name + "</font>" + "<font color='white'>" + " is burned for " + "</font>" + "<font color='red'>" + fireDam + "</font>" + "<font color='white'>" + " hit point(s)" + "</font>" + "<BR>"); crt.hp -= fireDam; } else if (filename.Equals("onHitTwoThreeFire.cs")) { float resist = (float)(1f - ((float)crt.damageTypeResistanceValueFire / 100f)); float damage = (1 * gv.sf.RandInt(2)) + 1; int fireDam = (int)(damage * resist); if (mod.debugMode) { gv.cc.addLogText("<font color='yellow'>" + "resist = " + resist + " damage = " + damage + " fireDam = " + fireDam + "</font>" + "<BR>"); } gv.cc.addLogText("<font color='aqua'>" + crt.cr_name + "</font>" + "<font color='white'>" + " is burned for " + "</font>" + "<font color='red'>" + fireDam + "</font>" + "<font color='white'>" + " hit point(s)" + "</font>" + "<BR>"); crt.hp -= fireDam; } else if (filename.Equals("onHitPcPoisonedLight.cs")) { int saveChkRoll = gv.sf.RandInt(20); int saveChk = saveChkRoll + pc.reflex; int DC = 13; if (saveChk >= DC) //passed save check { gv.cc.addLogText("<font color='yellow'>" + pc.name + " avoids being poisoned" + "</font>" + "<BR>"); if (mod.debugMode) { gv.cc.addLogText("<font color='yellow'>" + saveChkRoll + " + " + pc.reflex + " >= " + DC + "</font>" + "<BR>"); } } else //failed check { gv.cc.addLogText("<font color='red'>" + pc.name + " is poisoned" + "</font>" + "<BR>"); Effect ef = mod.getEffectByTag("poisonedLight"); pc.AddEffectByObject(ef, mod.WorldTime); } } else if (filename.Equals("onHitPcPoisonedMedium.cs")) { int saveChkRoll = gv.sf.RandInt(20); int saveChk = saveChkRoll + pc.reflex; int DC = 16; if (saveChk >= DC) //passed save check { gv.cc.addLogText("<font color='yellow'>" + pc.name + " avoids being poisoned" + "</font>" + "<BR>"); if (mod.debugMode) { gv.cc.addLogText("<font color='yellow'>" + saveChkRoll + " + " + pc.reflex + " >= " + DC + "</font>" + "<BR>"); } } else //failed check { gv.cc.addLogText("<font color='red'>" + pc.name + " is poisoned" + "</font>" + "<BR>"); Effect ef = mod.getEffectByTag("poisonedMedium"); pc.AddEffectByObject(ef, mod.WorldTime); } } } catch (Exception ex) { //IBMessageBox.Show(game, "failed to run script"); } } }
public int CalcCreatureDamageToPc(Player pc, Creature crt) { int dDam = crt.cr_damageDie; float damage = (crt.cr_damageNumDice * gv.sf.RandInt(dDam)) + crt.cr_damageAdder; if (damage < 0) { damage = 0; } float resist = 0; if (crt.cr_typeOfDamage.Equals("Acid")) { resist = (float)(1f - ((float)pc.damageTypeResistanceTotalAcid / 100f)); } else if (crt.cr_typeOfDamage.Equals("Normal")) { resist = (float)(1f - ((float)pc.damageTypeResistanceTotalNormal / 100f)); } else if (crt.cr_typeOfDamage.Equals("Cold")) { resist = (float)(1f - ((float)pc.damageTypeResistanceTotalCold / 100f)); } else if (crt.cr_typeOfDamage.Equals("Electricity")) { resist = (float)(1f - ((float)pc.damageTypeResistanceTotalElectricity / 100f)); } else if (crt.cr_typeOfDamage.Equals("Fire")) { resist = (float)(1f - ((float)pc.damageTypeResistanceTotalFire / 100f)); } else if (crt.cr_typeOfDamage.Equals("Magic")) { resist = (float)(1f - ((float)pc.damageTypeResistanceTotalMagic / 100f)); } else if (crt.cr_typeOfDamage.Equals("Poison")) { resist = (float)(1f - ((float)pc.damageTypeResistanceTotalPoison / 100f)); } int totalDam = (int)(damage * resist); if (totalDam < 0) { totalDam = 0; } return totalDam; }
public void doCreatureTurn() { canMove = true; //gv.cc.logScrollOffset = 0; Creature crt = mod.currentEncounter.encounterCreatureList[creatureIndex]; //do onTurn LT gv.cc.doLogicTreeBasedOnTag(gv.mod.currentEncounter.OnStartCombatTurnLogicTree, gv.mod.currentEncounter.OnStartCombatTurnParms); if ((crt.hp > 0) && (!crt.cr_status.Equals("Held"))) { creatureToAnimate = null; playerToAnimate = null; gv.Invalidate(); animationState = AnimationState.CreatureThink; gv.postDelayed("doAnimation", 5 * mod.combatAnimationSpeed); } else { endCreatureTurn(); } }
public int CalcCreatureAttackModifier(Creature crt) { if ((crt.cr_category.Equals("Ranged")) && (isAdjacentPc(crt))) { gv.cc.addLogText("<font color='yellow'>" + "-4 ranged attack penalty" + "</font>" + "<BR>"); gv.cc.addLogText("<font color='yellow'>" + "with enemies in melee range" + "</font>" + "<BR>"); gv.cc.floatyTextOn = true; gv.cc.addFloatyText(new Coordinate(crt.combatLocX, crt.combatLocY), "-4 att", "yellow"); gv.postDelayed("doFloatyText", 100); return crt.cr_att - 4; } else //melee weapon used { return crt.cr_att; } }
public void doCreatureAI(Creature crt) { //These are the current generic AI types //BasicAttacker: basic attack (ranged or melee) //Healer: heal Friend(s) until out of SP //BattleHealer: heal Friend(s) and/or attack //DamageCaster: cast damage spells //BattleDamageCaster: cast damage spells and/or attack //DebuffCaster: cast debuff spells //BattleDebuffCaster: cast debuff spells and/or attack //GeneralCaster: cast any of their known spells by random //BattleGeneralCaster: cast any of their known spells by random and/or attack if (crt.cr_ai.Equals("BasicAttacker")) { /*if (sf.frm.debugMode) { c.logText(crt.Name, Color.LightGray); c.logText(" is a BasicAttacker", Color.Black); c.logText(Environment.NewLine, Color.Black); }*/ BasicAttacker(crt); } else if (crt.cr_ai.Equals("GeneralCaster")) { /*if (sf.frm.debugMode) { c.logText(crt.Name, Color.LightGray); c.logText(" is a GeneralCaster", Color.Black); c.logText(Environment.NewLine, Color.Black); }*/ GeneralCaster(crt); } else { /*if (sf.frm.debugMode) { c.logText(crt.Name, Color.LightGray); c.logText(" is a BasicAttacker", Color.Black); c.logText(Environment.NewLine, Color.Black); }*/ BasicAttacker(crt); } }
public void CreatureCastsSpell(Creature crt) { Coordinate pnt = new Coordinate(); if (gv.sf.CombatTarget is Player) { Player pc = (Player)gv.sf.CombatTarget; pnt = new Coordinate(pc.combatLocX, pc.combatLocY); } else if (gv.sf.CombatTarget is Creature) { Creature crtTarget = (Creature)gv.sf.CombatTarget; pnt = new Coordinate(crtTarget.combatLocX, crtTarget.combatLocY); } else if (gv.sf.CombatTarget is Coordinate) { pnt = (Coordinate)gv.sf.CombatTarget; } else //do not understand, what is the target { //Toast.makeText(gv.gameContext, "can't figure out target.", Toast.LENGTH_SHORT).show(); return; } int endX = pnt.X * gv.squareSize + (gv.squareSize / 2); int endY = pnt.Y * gv.squareSize + (gv.squareSize / 2); int startX = crt.combatLocX * gv.squareSize + (gv.squareSize / 2); int startY = crt.combatLocY * gv.squareSize + (gv.squareSize / 2); if ((getDistance(pnt, new Coordinate(crt.combatLocX, crt.combatLocY)) <= gv.sf.SpellToCast.range) && (isVisibleLineOfSight(new Coordinate(endX, endY), new Coordinate(startX, startY)))) { if ((pnt.X < crt.combatLocX) && (!crt.combatFacingLeft)) //attack left { crt.token= gv.cc.flip(crt.token); crt.combatFacingLeft = true; } else if ((pnt.X > crt.combatLocX) && (crt.combatFacingLeft)) //attack right { crt.token= gv.cc.flip(crt.token); crt.combatFacingLeft = false; } creatureTargetLocation = pnt; //touchEnabled = false; creatureToAnimate = crt; playerToAnimate = null; gv.Invalidate(); animationState = AnimationState.CreatureCastAttackAnimation; gv.postDelayed("doAnimation", 5 * mod.combatAnimationSpeed); } else { //#region Do a Melee or Ranged Attack Player pc = targetClosestPC(crt); gv.sf.CombatTarget = pc; CreatureDoesAttack(crt); } }
public bool isAdjacentPc(Creature crt) { foreach (Player pc in mod.playerList) { if (getDistance(new Coordinate(pc.combatLocX,pc.combatLocY), new Coordinate(crt.combatLocX,crt.combatLocY)) == 1) { return true; } } return false; }
public void CreatureDoesAttack(Creature crt) { if (gv.sf.CombatTarget != null) { Player pc = (Player)gv.sf.CombatTarget; int endX = pc.combatLocX * gv.squareSize + (gv.squareSize / 2); int endY = pc.combatLocY * gv.squareSize + (gv.squareSize / 2); int startX = crt.combatLocX * gv.squareSize + (gv.squareSize / 2); int startY = crt.combatLocY * gv.squareSize + (gv.squareSize / 2); // determine if ranged or melee if ((crt.cr_category.Equals("Ranged")) && (CalcDistance(crt.combatLocX, crt.combatLocY, pc.combatLocX, pc.combatLocY) <= crt.cr_attRange) && (isVisibleLineOfSight(new Coordinate(endX, endY), new Coordinate(startX, startY)))) { //Point starting = new Point((crt_pt.CombatLocation.X * gm._squareSize) + (gm._squareSize / 2), (crt_pt.CombatLocation.Y * gm._squareSize) + (gm._squareSize / 2)); //Point ending = new Point((char_pt.CombatLocation.X * gm._squareSize) + (gm._squareSize / 2), (char_pt.CombatLocation.Y * gm._squareSize) + (gm._squareSize / 2)); //frm.currentCombat.playCreatureAttackSound(crt_pt); //play attack sound for ranged gv.PlaySound(crt.cr_attackSound); //frm.currentCombat.drawProjectile(starting, ending, crt_pt.ProjectileSpriteFilename); if ((pc.combatLocX < crt.combatLocX) && (!crt.combatFacingLeft)) //attack left { crt.token= gv.cc.flip(crt.token); crt.combatFacingLeft = true; } else if ((pc.combatLocX > crt.combatLocX) && (crt.combatFacingLeft)) //attack right { crt.token= gv.cc.flip(crt.token); crt.combatFacingLeft = false; } if (crt.hp > 0) { //doStandardCreatureAttack(crt, pc); creatureToAnimate = crt; playerToAnimate = null; gv.Invalidate(); creatureTargetLocation = new Coordinate(pc.combatLocX, pc.combatLocY); animationState = AnimationState.CreatureRangedAttackAnimation; gv.postDelayed("doAnimation", 5 * mod.combatAnimationSpeed); } else { //skip this guys turn } } else if ((crt.cr_category.Equals("Melee")) && (CalcDistance(crt.combatLocX, crt.combatLocY, pc.combatLocX, pc.combatLocY) <= crt.cr_attRange)) { if ((pc.combatLocX < crt.combatLocX) && (!crt.combatFacingLeft)) //attack left { crt.token= gv.cc.flip(crt.token); crt.combatFacingLeft = true; } else if ((pc.combatLocX > crt.combatLocX) && (crt.combatFacingLeft)) //attack right { crt.token= gv.cc.flip(crt.token); crt.combatFacingLeft = false; } if (crt.hp > 0) { //doStandardCreatureAttack(crt, pc); creatureToAnimate = crt; playerToAnimate = null; gv.Invalidate(); animationState = AnimationState.CreatureMeleeAttackAnimation; gv.postDelayed("doAnimation", 5 * mod.combatAnimationSpeed); //creatureTurnState = "attackAnim"; } else { //skip this guys turn } } else //not in range for attack so MOVE { CreatureMoves(); } } else //no target so move instead { CreatureMoves(); } }
public int CalcPcDamageToCreature(Player pc, Creature crt) { int damModifier = 0; int adder = 0; bool melee = false; if ((mod.getItemByResRefForInfo(pc.MainHandRefs.resref).category.Equals("Melee")) || (pc.MainHandRefs.name.Equals("none")) || (mod.getItemByResRefForInfo(pc.AmmoRefs.resref).name.Equals("none"))) { melee = true; damModifier = (pc.strength - 10) / 2; //if has critical strike trait use dexterity for damage modifier in melee if greater than strength modifier if (gv.sf.hasTrait(pc, "criticalstrike")) { int damModifierDex = (pc.dexterity - 10) / 4; if (damModifierDex > damModifier) { damModifier = (pc.dexterity - 10) / 2; } } } else //ranged weapon used { damModifier = 0; if (gv.sf.hasTrait(pc, "preciseshot2")) { damModifier += 2; gv.cc.addLogText("<font color='lime'> PreciseShotL2: +2 damage</font><BR>"); } else if (gv.sf.hasTrait(pc, "preciseshot")) { damModifier++; gv.cc.addLogText("<font color='lime'> PreciseShotL1: +1 damage</font><BR>"); } } int dDam = mod.getItemByResRefForInfo(pc.MainHandRefs.resref).damageDie; float damage = (mod.getItemByResRefForInfo(pc.MainHandRefs.resref).damageNumDice * gv.sf.RandInt(dDam)) + damModifier + adder + mod.getItemByResRefForInfo(pc.MainHandRefs.resref).damageAdder; if (damage < 0) { damage = 0; } Item it = mod.getItemByResRefForInfo(pc.AmmoRefs.resref); if (it != null) { damage += mod.getItemByResRefForInfo(pc.AmmoRefs.resref).damageAdder; } float resist = 0; if (mod.getItemByResRefForInfo(pc.MainHandRefs.resref).typeOfDamage.Equals("Acid")) { resist = (float)(1f - ((float)crt.damageTypeResistanceValueAcid / 100f)); } else if (mod.getItemByResRefForInfo(pc.MainHandRefs.resref).typeOfDamage.Equals("Normal")) { resist = (float)(1f - ((float)crt.damageTypeResistanceValueNormal / 100f)); } else if (mod.getItemByResRefForInfo(pc.MainHandRefs.resref).typeOfDamage.Equals("Cold")) { resist = (float)(1f - ((float)crt.damageTypeResistanceValueCold / 100f)); } else if (mod.getItemByResRefForInfo(pc.MainHandRefs.resref).typeOfDamage.Equals("Electricity")) { resist = (float)(1f - ((float)crt.damageTypeResistanceValueElectricity / 100f)); } else if (mod.getItemByResRefForInfo(pc.MainHandRefs.resref).typeOfDamage.Equals("Fire")) { resist = (float)(1f - ((float)crt.damageTypeResistanceValueFire / 100f)); } else if (mod.getItemByResRefForInfo(pc.MainHandRefs.resref).typeOfDamage.Equals("Magic")) { resist = (float)(1f - ((float)crt.damageTypeResistanceValueMagic / 100f)); } else if (mod.getItemByResRefForInfo(pc.MainHandRefs.resref).typeOfDamage.Equals("Poison")) { resist = (float)(1f - ((float)crt.damageTypeResistanceValuePoison / 100f)); } int totalDam = (int)(damage * resist); if (totalDam < 0) { totalDam = 0; } //if doing sneak attack, does extra damage if ((pc.steathModeOn) && (melee)) { if (pc.knownTraitsTags.Contains("sneakattack")) { //+1d6 for every 2 levels after level 1 int multiplier = ((pc.classLevel - 1) / 2) + 1; int adding = 0; for (int i = 0; i < multiplier; i++) { adding += gv.sf.RandInt(6); } totalDam += adding; gv.cc.addLogText("<font color='lime'> sneak attack: +" + adding + " damage</font><BR>"); if (mod.debugMode) //SD_20131102 { //gv.cc.addLogText("<font color='yellow'> sneak attack: +" + adding + " damage</font><BR>"); } } } return totalDam; }
public bool doActualCreatureAttack(Player pc, Creature crt, int attackNumber) { int attackRoll = gv.sf.RandInt(20); int attackMod = CalcCreatureAttackModifier(crt); int defense = CalcPcDefense(pc, crt); int damage = CalcCreatureDamageToPc(pc, crt); int attack = attackRoll + attackMod; if ((attack >= defense) || (attackRoll == 20)) { pc.hp = pc.hp - damage; gv.cc.addLogText("<font color='silver'>" + crt.cr_name + "</font>" + "<font color='white'>" + " attacks " + "</font>" + "<font color='aqua'>" + pc.name + "</font>" + "<BR>"); gv.cc.addLogText("<font color='white'>" + " and HITS (" + "</font>" + "<font color='red'>" + damage + "</font>" + "<font color='white'>" + " damage)" + "</font>" + "<BR>"); gv.cc.addLogText("<font color='white'>" + attackRoll + " + " + attackMod + " >= " + defense + "</font>" + "<BR>"); //#region onScoringHit script of creature doOnHitScriptBasedOnFilename(crt.onScoringHit, crt, pc); //#endregion //Draw floaty text showing damage above PC int txtH = (int)gv.drawFontReg.Height; int shiftUp = 0 - (attackNumber * txtH); floatyTextOn = true; gv.cc.addFloatyText(new Coordinate(pc.combatLocX, pc.combatLocY), damage + "", shiftUp); gv.postDelayed("doFloatyText", 100); if (pc.hp <= 0) { gv.cc.addLogText("<font color='red'>" + pc.name + " drops down unconsciously!" + "</font>" + "<BR>"); pc.charStatus = "Dead"; } return true; } else { gv.cc.addLogText("<font color='silver'>" + crt.cr_name + "</font>" + "<font color='white'>" + " attacks " + "</font>" + "<font color='aqua'>" + pc.name + "</font>" + "<BR>"); gv.cc.addLogText("<font color='white'>" + " and MISSES" + "</font>" + "<BR>"); gv.cc.addLogText("<font color='white'>" + attackRoll + " + " + attackMod + " < " + defense + "</font>" + "<BR>"); return false; } }
public int CalcPcDefense(Player pc, Creature crt) { //pc.UpdateStats(this); int defense = pc.AC; if (pc.charStatus.Equals("Held")) { defense -= 4; gv.cc.addFloatyText(new Coordinate(pc.combatLocX, pc.combatLocY), "+4 att", "yellow"); } return defense; }
//called from outside to get next move location public Coordinate findNewPoint(Creature crt, Coordinate end) { foundEnd = false; Coordinate newPoint = new Coordinate(-1,-1); //set start value to 0 values[crt.combatLocX,crt.combatLocY] = 0; foreach (Creature cr in mod.currentEncounter.encounterCreatureList) { if (cr != crt) grid[cr.combatLocX,cr.combatLocY] = 1; } foreach (Player p in mod.playerList) { if ((!p.charStatus.Equals("Dead")) && (p.hp > 0)) { grid[p.combatLocX,p.combatLocY] = 1; } } grid[crt.combatLocX,crt.combatLocY] = 2; grid[end.X,end.Y] = 3; buildPath(); if (!foundEnd) { //do not build path for now so return (-1,-1), later add code for picking a spot to move } else { pathNodes.Add(new Coordinate(end.X, end.Y)); for (int i = 0; i < values[end.X,end.Y]; i++) { pathNodes.Add(getLowestNeighbor(pathNodes[pathNodes.Count - 1])); } //build list of path points newPoint = pathNodes[pathNodes.Count - 2]; } return newPoint; }
public void TargetAttack(Player pc) { if (isValidAttackTarget(pc)) { if ((targetHighlightCenterLocation.X < pc.combatLocX) && (!pc.combatFacingLeft)) //attack left { pc.token = gv.cc.flip(pc.token); pc.combatFacingLeft = true; } else if ((targetHighlightCenterLocation.X > pc.combatLocX) && (pc.combatFacingLeft)) //attack right { pc.token = gv.cc.flip(pc.token); pc.combatFacingLeft = false; } gv.touchEnabled = false; creatureToAnimate = null; playerToAnimate = pc; gv.Invalidate(); if ((mod.getItemByResRefForInfo(pc.MainHandRefs.resref).category.Equals("Melee")) || (mod.getItemByResRefForInfo(pc.MainHandRefs.resref).name.Equals("none")) || (mod.getItemByResRefForInfo(pc.AmmoRefs.resref).name.Equals("none"))) { animationState = AnimationState.PcMeleeAttackAnimation; } else { //play attack sound for ranged gv.PlaySound(mod.getItemByResRefForInfo(pc.MainHandRefs.resref).itemOnUseSound); animationState = AnimationState.PcRangedAttackAnimation; } gv.postDelayed("doAnimation", 5 * mod.combatAnimationSpeed); } }
//called from outside to get next move location public Coordinate findNewPoint(Creature crt, Coordinate end) { foundEnd = false; Coordinate newPoint = new Coordinate(-1, -1); //set start value to 0 values[crt.combatLocX, crt.combatLocY] = 0; foreach (Creature cr in mod.currentEncounter.encounterCreatureList) { if (cr != crt) grid[cr.combatLocX, cr.combatLocY] = 1; } foreach (Player p in mod.playerList) { if ((!p.charStatus.Equals("Dead")) && (p.hp > 0)) { grid[p.combatLocX, p.combatLocY] = 1; } } //find all props that have collision and set there square to 1 /*TODO add props to encounters foreach (Prop prp in mod.currentEncounter.Props) { if ( ((prp.HasCollision) && (prp.isActive)) || ((prp.isMover) && (prp.isActive)) ) { grid[prp.LocationX,prp.LocationY] = 1; } }*/ grid[crt.combatLocX, crt.combatLocY] = 2; //2 marks the start point in the grid grid[end.X, end.Y] = 3; //3 marks the end point in the grid buildPath(); if (!foundEnd) { //do not build path for now so return (-1,-1), later add code for picking a spot to move } else { pathNodes.Add(new Coordinate(end.X, end.Y)); for (int i = 0; i < 9999; i++) //keep going until full path back to crt is built { pathNodes.Add(getLowestNeighbor(pathNodes[pathNodes.Count - 1])); if ((pathNodes[pathNodes.Count - 1].X == crt.combatLocX ) && (pathNodes[pathNodes.Count - 1].Y == crt.combatLocY )) { break; } } //build list of path points newPoint = pathNodes[pathNodes.Count - 2]; } return newPoint; }
public Creature DeepCopy() { Creature copy = new Creature(); copy.cr_tokenFilename = this.cr_tokenFilename; copy.combatFacingLeft = this.combatFacingLeft; copy.combatLocX = this.combatLocX; copy.combatLocY = this.combatLocY; copy.cr_name = this.cr_name; copy.cr_tag = this.cr_tag; copy.cr_resref = this.cr_resref; copy.cr_desc = this.cr_desc; copy.cr_level = this.cr_level; copy.hp = this.hp; copy.hpMax = this.hpMax; copy.sp = this.sp; copy.cr_XP = this.cr_XP; copy.AC = this.AC; copy.cr_status = this.cr_status; copy.cr_att = this.cr_att; copy.cr_attRange = this.cr_attRange; copy.cr_damageNumDice = this.cr_damageNumDice; copy.cr_damageDie = this.cr_damageDie; copy.cr_damageAdder = this.cr_damageAdder; copy.cr_category = this.cr_category; copy.cr_projSpriteFilename = this.cr_projSpriteFilename; copy.cr_spriteEndingFilename = this.cr_spriteEndingFilename; copy.cr_attackSound = this.cr_attackSound; copy.cr_numberOfAttacks = this.cr_numberOfAttacks; copy.cr_ai = this.cr_ai; copy.fortitude = this.fortitude; copy.will = this.will; copy.reflex = this.reflex; copy.damageTypeResistanceValueAcid = this.damageTypeResistanceValueAcid; copy.damageTypeResistanceValueNormal = this.damageTypeResistanceValueNormal; copy.damageTypeResistanceValueCold = this.damageTypeResistanceValueCold; copy.damageTypeResistanceValueElectricity = this.damageTypeResistanceValueElectricity; copy.damageTypeResistanceValueFire = this.damageTypeResistanceValueFire; copy.damageTypeResistanceValueMagic = this.damageTypeResistanceValueMagic; copy.damageTypeResistanceValuePoison = this.damageTypeResistanceValuePoison; copy.cr_typeOfDamage = this.cr_typeOfDamage; copy.onScoringHit = this.onScoringHit; copy.onScoringHitParms = this.onScoringHitParms; copy.onDeathLogicTree = this.onDeathLogicTree; copy.onDeathParms = this.onDeathParms; copy.cr_effectsList = new List<Effect>(); copy.knownSpellsTags = new List<string>(); foreach (string s in this.knownSpellsTags) { copy.knownSpellsTags.Add(s); } copy.CreatureLocalInts = new List<LocalInt>(); foreach (LocalInt l in this.CreatureLocalInts) { LocalInt Lint = new LocalInt(); Lint.Key = l.Key; Lint.Value = l.Value; copy.CreatureLocalInts.Add(Lint); } copy.CreatureLocalStrings = new List<LocalString>(); foreach (LocalString l in this.CreatureLocalStrings) { LocalString Lstr = new LocalString(); Lstr.Key = l.Key; Lstr.Value = l.Value; copy.CreatureLocalStrings.Add(Lstr); } return copy; }