public static string AttackSequence(Player attacker, Player victim, SkillViewModel skillBeingUsed, bool timestamp = true) { // Actual attack var(_, message) = AttackProcedures.Attack(attacker, victim, skillBeingUsed, timestamp); // record into statistics StatsProcedures.AddStat(attacker.MembershipId, StatsProcedures.Stat__SpellsCast, 1); if (AIStatics.IsABoss(victim.BotId)) { StatsProcedures.AddStat(attacker.MembershipId, StatsProcedures.Stat__BossAllAttacks, 1); } if (victim.BotId == AIStatics.FemaleRatBotId || victim.BotId == AIStatics.MaleRatBotId) { StatsProcedures.AddStat(attacker.MembershipId, StatsProcedures.Stat__BossRatThiefAttacks, 1); } else if (victim.BotId == AIStatics.BimboBossBotId) { StatsProcedures.AddStat(attacker.MembershipId, StatsProcedures.Stat__BossLovebringerAttacks, 1); } else if (victim.BotId == AIStatics.DonnaBotId) { StatsProcedures.AddStat(attacker.MembershipId, StatsProcedures.Stat__BossDonnaAttacks, 1); } else if (victim.BotId == AIStatics.FaebossBotId) { StatsProcedures.AddStat(attacker.MembershipId, StatsProcedures.Stat__FaebossAttacks, 1); } else if (victim.BotId == AIStatics.MouseNerdBotId || victim.BotId == AIStatics.MouseBimboBotId) { StatsProcedures.AddStat(attacker.MembershipId, StatsProcedures.Stat__MouseSisterAttacks, 1); } else if (victim.BotId == AIStatics.MotorcycleGangLeaderBotId) { StatsProcedures.AddStat(attacker.MembershipId, StatsProcedures.Stat__MotorcycleGangAttacks, 1); } else if (AIStatics.IsAMiniboss(victim.BotId) && victim.BotId != AIStatics.MinibossPlushAngelId) // The plush just wants to make friends. No rewards for monsters. { StatsProcedures.AddStat(attacker.MembershipId, StatsProcedures.Stat__MinibossAttacks, 1); } // Trigger any counterattack AIProcedures.CheckAICounterattackRoutine(attacker, victim); return(message); }
private static void PerformAnimateTransformation(Player victim, Player attacker, DbStaticForm targetForm, LogBox output) { var playerRepo = new EFPlayerRepository(); var dbVictim = playerRepo.Players.FirstOrDefault(p => p.Id == victim.Id); SkillProcedures.UpdateFormSpecificSkillsToPlayer(dbVictim, targetForm.Id); DomainRegistry.Repository.Execute(new ChangeForm { PlayerId = dbVictim.Id, FormSourceId = targetForm.Id }); // wipe out half of the target's mana dbVictim.Mana -= dbVictim.MaxMana / 2; if (dbVictim.Mana < 0) { dbVictim.Mana = 0; } // Remove any Self Restore entires. RemoveSelfRestore(dbVictim); var targetbuffs = ItemProcedures.GetPlayerBuffs(dbVictim); dbVictim = PlayerProcedures.ReadjustMaxes(dbVictim, targetbuffs); // take away some of the victim's XP based on the their level // target.XP += -2.5M * target.Level; playerRepo.SavePlayer(dbVictim); output.LocationLog += $"<br><b>{dbVictim.GetFullName()} was completely transformed into a {targetForm.FriendlyName} here.</b>"; output.AttackerLog += $"<br><b>You fully transformed {dbVictim.GetFullName()} into a {targetForm.FriendlyName}</b>!"; output.VictimLog += $"<br><b>You have been fully transformed into a {targetForm.FriendlyName}!</b>"; // Let the target know they are best friends with the angel plush. if (attacker.BotId == AIStatics.MinibossPlushAngelId) { output.VictimLog += $"<br><br><b>{attacker.GetFullName()}</b> was happy to make you into a new friend!<br>"; } TFEnergyProcedures.DeleteAllPlayerTFEnergiesOfFormSourceId(dbVictim.Id, targetForm.Id); StatsProcedures.AddStat(dbVictim.MembershipId, StatsProcedures.Stat__TimesAnimateTFed, 1); StatsProcedures.AddStat(attacker.MembershipId, StatsProcedures.Stat__TimesAnimateTFing, 1); }
public static void AddDiscoverableSpellStat(string membershipId, string stat) { var numDiscoverableSpells = SkillStatics.GetNumPlayerLearnableSkills(); StatsProcedures.AddStat(membershipId, stat, 1, numDiscoverableSpells); }
public static string ReturnToAnimate(Player player, bool dungeonPenalty) { IInanimateXPRepository inanimXpRepo = new EFInanimateXPRepository(); IItemRepository itemRepo = new EFItemRepository(); var inanimXP = inanimXpRepo.InanimateXPs.FirstOrDefault(i => i.OwnerId == player.Id); var currentGameTurn = PvPWorldStatProcedures.GetWorldTurnNumber(); if (inanimXP == null) { inanimXP = new InanimateXP { OwnerId = player.Id, Amount = 0, // set the initial times struggled proportional to how high of a level the player is TimesStruggled = -6 * player.Level, LastActionTimestamp = DateTime.UtcNow, LastActionTurnstamp = currentGameTurn - 1, }; } double strugglebonus = currentGameTurn - inanimXP.LastActionTurnstamp; if (strugglebonus > TurnTimesStatics.GetItemMaxTurnsBuildup()) { strugglebonus = TurnTimesStatics.GetItemMaxTurnsBuildup(); } if (strugglebonus < 0) { strugglebonus = 0; } if (PvPStatics.ChaosMode) { strugglebonus = 100; } // increment the player's attack count. Also decrease their player XP some. IPlayerRepository playerRepo = new EFPlayerRepository(); var dbPlayer = playerRepo.Players.FirstOrDefault(p => p.Id == player.Id); dbPlayer.TimesAttackingThisUpdate++; var strugglesMade = Convert.ToDouble(GetStruggleChance(player, dungeonPenalty)); var rand = new Random(); var roll = rand.NextDouble() * 100; var dbPlayerItem = DomainRegistry.Repository.FindSingle(new GetItemByFormerPlayer { PlayerId = player.Id }); if (dbPlayerItem == null) { return("Cannot struggle - no player item"); } if (dbPlayerItem.Owner != null) { var owner = PlayerProcedures.GetPlayer(dbPlayerItem.Owner.Id); dbPlayer.dbLocationName = owner.dbLocationName; } var itemPlus = ItemStatics.GetStaticItem(dbPlayerItem.ItemSource.Id); if (roll < strugglesMade) { // assert that the covenant the victim is in is not too full to accept them back in if (dbPlayer.Covenant > 0) { var victimCov = CovenantProcedures.GetCovenantViewModel((int)dbPlayer.Covenant).dbCovenant; if (victimCov != null && CovenantProcedures.GetPlayerCountInCovenant(victimCov, true) >= PvPStatics.Covenant_MaximumAnimatePlayerCount) { return("Although you had enough energy to break free from your body as a " + itemPlus.FriendlyName + " and restore your regular body, you were unfortunately not able to break free because there is no more room in your covenant for any more animate mages."); } } // if the item has an owner, notify them via a message. if (dbPlayerItem.Owner != null) { var message = player.FirstName + " " + player.LastName + ", your " + itemPlus.FriendlyName + ", successfully struggles against your magic and reverses their transformation. You can no longer claim them as your property, not unless you manage to turn them back again..."; PlayerLogProcedures.AddPlayerLog(dbPlayerItem.Owner.Id, message, true); } // change the player's form and mobility DomainRegistry.Repository.Execute(new ChangeForm { PlayerId = dbPlayer.Id, FormSourceId = dbPlayer.OriginalFormSourceId }); dbPlayer.ActionPoints = TurnTimesStatics.GetActionPointLimit(); dbPlayer.ActionPoints_Refill = TurnTimesStatics.GetActionPointReserveLimit(); dbPlayer.CleansesMeditatesThisRound = PvPStatics.MaxCleansesMeditatesPerUpdate; dbPlayer.TimesAttackingThisUpdate = PvPStatics.MaxAttacksPerUpdate; // don't let the player spawn in the dungeon as they will have Back On Your Feet // and may not be meet the level and game mode requirements if (dbPlayer.IsInDungeon()) { dbPlayer.dbLocationName = LocationsStatics.GetRandomLocationNotInDungeon(); } dbPlayer = PlayerProcedures.ReadjustMaxes(dbPlayer, ItemProcedures.GetPlayerBuffs(dbPlayer)); dbPlayer.Health = dbPlayer.MaxHealth / 3; dbPlayer.Mana = dbPlayer.MaxHealth / 3; playerRepo.SavePlayer(dbPlayer); // drop any runes embedded on the player-item, or return them to the former owner's inventory DomainRegistry.Repository.Execute(new UnbembedRunesOnItem { ItemId = dbPlayerItem.Id }); // delete the item or animal that this player had turned into itemRepo.DeleteItem(dbPlayerItem.Id); // delete the inanimate XP item inanimXpRepo.DeleteInanimateXP(inanimXP.Id); // give the player the recovery buff EffectProcedures.GivePerkToPlayer(PvPStatics.Effect_BackOnYourFeetSourceId, dbPlayer); var msg = "You have managed to break free from your form as " + itemPlus.FriendlyName + " and occupy an animate body once again!"; if (PvPStatics.ChaosMode) { msg += $" [CHAOS MODE: Struggle value overriden to {strugglebonus:0}% per struggle.]"; } PlayerLogProcedures.AddPlayerLog(dbPlayer.Id, msg, false); StatsProcedures.AddStat(dbPlayer.MembershipId, StatsProcedures.Stat__SuccessfulStruggles, 1); return(msg); } // failure to break free; increase time struggles else { // raise the probability of success for next time somewhat proportion to how many turns they missed inanimXP.TimesStruggled += Convert.ToInt32(strugglebonus); inanimXP.LastActionTimestamp = DateTime.UtcNow; inanimXP.LastActionTurnstamp = currentGameTurn; inanimXpRepo.SaveInanimateXP(inanimXP); playerRepo.SavePlayer(dbPlayer); if (dbPlayerItem.Owner != null) { var message = $"{player.FirstName} {player.LastName}, your {itemPlus.FriendlyName}, struggles but fails to return to an animate form. [Recovery chance next struggle: {(int)GetStruggleChance(player, dungeonPenalty)}%]"; PlayerLogProcedures.AddPlayerLog(dbPlayerItem.Owner.Id, message, true); } PlayerLogProcedures.AddPlayerLog(dbPlayer.Id, "You struggled to return to a human form.", false); return($"Unfortunately you are not able to struggle free from your form as {itemPlus.FriendlyName}. Keep trying and you might succeed later... [Recovery chance next struggle: {(int)GetStruggleChance(player, dungeonPenalty)}%]"); } }
public static string GiveInanimateXP(string membershipId, bool isWhitelist) { IInanimateXPRepository inanimXpRepo = new EFInanimateXPRepository(); IItemRepository itemRep = new EFItemRepository(); // get the current level of this player based on what item they are var me = PlayerProcedures.GetPlayerFromMembership(membershipId); var inanimateMeHack = DomainRegistry.Repository.FindSingle(new GetItemByFormerPlayer { PlayerId = me.Id }); var inanimateMe = itemRep.Items.FirstOrDefault(i => i.Id == inanimateMeHack.Id); // TODO: Replace with proper Command var currentGameTurn = PvPWorldStatProcedures.GetWorldTurnNumber(); decimal xpGain = 0; // get the number of inanimate accounts under this IP IPlayerRepository playerRepo = new EFPlayerRepository(); decimal playerCount = playerRepo.Players.Count(p => p.IpAddress == me.IpAddress && (p.Mobility == PvPStatics.MobilityInanimate || p.Mobility == PvPStatics.MobilityPet) && p.BotId == AIStatics.ActivePlayerBotId); if (playerCount == 0 || isWhitelist) { playerCount = 1; } var xp = inanimXpRepo.InanimateXPs.FirstOrDefault(i => i.OwnerId == me.Id); if (xp == null) { xp = new InanimateXP { OwnerId = me.Id, Amount = xpGain / playerCount, TimesStruggled = -6 * me.Level, LastActionTimestamp = DateTime.UtcNow, LastActionTurnstamp = currentGameTurn - 1, }; if (me.Mobility == PvPStatics.MobilityInanimate) { StatsProcedures.AddStat(me.MembershipId, StatsProcedures.Stat__InanimateXPEarned, (float)xpGain); } else if (me.Mobility == PvPStatics.MobilityPet) { StatsProcedures.AddStat(me.MembershipId, StatsProcedures.Stat__PetXPEarned, (float)xpGain); } } else { double turnsSinceLastAction = currentGameTurn - xp.LastActionTurnstamp; if (turnsSinceLastAction > TurnTimesStatics.GetItemMaxTurnsBuildup()) { turnsSinceLastAction = TurnTimesStatics.GetItemMaxTurnsBuildup(); } if (turnsSinceLastAction < 0) { turnsSinceLastAction = 0; } xpGain += Convert.ToDecimal(turnsSinceLastAction) * InanimateXPStatics.XPGainPerInanimateAction; xpGain = xpGain / playerCount; if (me.Mobility == PvPStatics.MobilityInanimate) { StatsProcedures.AddStat(me.MembershipId, StatsProcedures.Stat__InanimateXPEarned, (float)xpGain); } else if (me.Mobility == PvPStatics.MobilityPet) { StatsProcedures.AddStat(me.MembershipId, StatsProcedures.Stat__PetXPEarned, (float)xpGain); } xp.Amount += xpGain; xp.TimesStruggled -= 2 * Convert.ToInt32(turnsSinceLastAction); xp.LastActionTimestamp = DateTime.UtcNow; xp.LastActionTurnstamp = currentGameTurn; } var resultMessage = " "; if (xp.Amount >= Convert.ToDecimal(ItemProcedures.GetXPRequiredForItemPetLevelup(inanimateMe.Level))) { xp.Amount -= Convert.ToDecimal(ItemProcedures.GetXPRequiredForItemPetLevelup(inanimateMe.Level)); inanimateMe.Level++; itemRep.SaveItem(inanimateMe); resultMessage += $" You have gained {xpGain:0.#} xp. <b>Congratulations, you have gained a level! Your owner will be so proud...</b>"; var wearerMessage = "<span style='color: darkgreen'>" + me.FirstName + " " + me.LastName + ", currently your " + ItemStatics.GetStaticItem(inanimateMe.ItemSourceId).FriendlyName + ", has gained a level! Treat them kindly and they might keep helping you out...</span>"; // now we need to change the owner's max health or mana based on this leveling if (inanimateMe.OwnerId > 0) { PlayerLogProcedures.AddPlayerLog((int)inanimateMe.OwnerId, wearerMessage, true); var inanimateMePlus = ItemProcedures.GetItemViewModel(inanimateMe.Id); if (inanimateMePlus.Item.HealthBonusPercent != 0.0M || inanimateMePlus.Item.ManaBonusPercent != 0.0M) { var myowner = playerRepo.Players.FirstOrDefault(p => p.Id == inanimateMe.OwnerId); var healthChange = PvPStatics.Item_LevelBonusModifier * inanimateMePlus.Item.HealthBonusPercent; var manaChange = PvPStatics.Item_LevelBonusModifier * inanimateMePlus.Item.ManaBonusPercent; myowner.MaxHealth += healthChange; myowner.MaxMana += manaChange; if (myowner.MaxHealth < 1) { myowner.MaxHealth = 1; } if (myowner.MaxMana < 1) { myowner.MaxMana = 1; } if (myowner.Health > myowner.MaxHealth) { myowner.Health = myowner.MaxHealth; } if (myowner.Mana > myowner.MaxMana) { myowner.Mana = myowner.MaxMana; } playerRepo.SavePlayer(myowner); } } } else { resultMessage = $" You have gained {xpGain:0.#} xp. ({xp.Amount:0.#}/{ItemProcedures.GetXPRequiredForItemPetLevelup(inanimateMe.Level):0.#} to next level)."; } inanimXpRepo.SaveInanimateXP(xp); // lock the player into their fate if their inanimate XP gets too high if (xp.TimesStruggled <= TurnTimesStatics.GetStruggleXPBeforeItemPermanentLock() * .5 && xp.TimesStruggled > TurnTimesStatics.GetStruggleXPBeforeItemPermanentLock() && !inanimateMe.IsPermanent) { resultMessage += " Careful, if you keep doing this you may find yourself stuck in your current form forever..."; } if (xp.TimesStruggled <= TurnTimesStatics.GetStruggleXPBeforeItemPermanentLock() && !inanimateMe.IsPermanent) { inanimateMe.IsPermanent = true; itemRep.SaveItem(inanimateMe); DomainRegistry.Repository.Execute(new RemoveSoulbindingOnPlayerItems { PlayerId = me.Id }); DomainRegistry.Repository.Execute(new DropAllItems { PlayerId = me.Id, IgnoreRunes = false }); var formRepo = new EFDbStaticFormRepository(); var form = formRepo.DbStaticForms.FirstOrDefault(f => f.Id == me.FormSourceId); if (inanimateMe.OwnerId != null && form != null) { PlayerLogProcedures.AddPlayerLog(inanimateMe.OwnerId.Value, $"{me.GetFullName()} has locked and is now unable to escape their form as your {form.FriendlyName}!", true); } PlayerLogProcedures.AddPlayerLog(me.Id, $"You have locked in your current form as a {form.FriendlyName}!", false); resultMessage += " <b>You find the last of your old human self slip away as you permanently embrace your new form.</b>"; } return(resultMessage); }
private static void PerformInanimateTransformation(Player victim, Player attacker, int skillSourceId, DbStaticForm targetForm, LogBox output) { SkillProcedures.UpdateFormSpecificSkillsToPlayer(victim, targetForm.Id); DomainRegistry.Repository.Execute(new ChangeForm { PlayerId = victim.Id, FormSourceId = targetForm.Id }); if (targetForm.MobilityType == PvPStatics.MobilityInanimate && victim.BotId != AIStatics.MinibossPlushAngelId) //No reward for monsters that hurt an innocent little plush friend. :( { StatsProcedures.AddStat(victim.MembershipId, StatsProcedures.Stat__TimesInanimateTFed, 1); StatsProcedures.AddStat(attacker.MembershipId, StatsProcedures.Stat__TimesInanimateTFing, 1); } else if (targetForm.MobilityType == PvPStatics.MobilityPet && victim.BotId != AIStatics.MinibossPlushAngelId) //No reward for monsters that hurt an innocent little plush friend. :( { StatsProcedures.AddStat(victim.MembershipId, StatsProcedures.Stat__TimesAnimalTFed, 1); StatsProcedures.AddStat(attacker.MembershipId, StatsProcedures.Stat__TimesAnimalTFing, 1); } if (targetForm.MobilityType == PvPStatics.MobilityPet || targetForm.MobilityType == PvPStatics.MobilityInanimate) { if (victim.BotId == AIStatics.PsychopathBotId) { StatsProcedures.AddStat(attacker.MembershipId, StatsProcedures.Stat__PsychopathsDefeated, 1); } if (victim.BotId == AIStatics.ActivePlayerBotId && attacker.GameMode == (int)GameModeStatics.GameModes.PvP && victim.GameMode == (int)GameModeStatics.GameModes.PvP) { StatsProcedures.AddStat(attacker.MembershipId, StatsProcedures.Stat__PvPPlayerNumberTakedowns, 1); StatsProcedures.AddStat(attacker.MembershipId, StatsProcedures.Stat__PvPPlayerLevelTakedowns, victim.Level); } } // extra log stuff for turning into item var extra = ItemProcedures.PlayerBecomesItem(victim, targetForm, attacker); output.AttackerLog += extra.AttackerLog; output.VictimLog += extra.VictimLog; output.LocationLog += extra.LocationLog; // give some of the victim's money to the attacker, the amount depending on what mode the victim is in var moneygain = victim.Money * .35M; PlayerProcedures.GiveMoneyToPlayer(attacker, moneygain); PlayerProcedures.GiveMoneyToPlayer(victim, -moneygain / 2); var levelDifference = attacker.Level - victim.Level; // only give the lump sum XP if the victim is not in the same covenant if (attacker.Covenant == null || attacker.Covenant != victim.Covenant) { var xpGain = 100 - (PvPStatics.XP__EndgameTFCompletionLevelBase * levelDifference); if (xpGain < 50) { xpGain = 50; } else if (xpGain > 200) { xpGain = 200; } // give the attacker a nice lump sum for having completed the transformation output.AttackerLog += $" <br>For having sealed your opponent into their new form, you gain an extra <b>{xpGain}</b> XP."; output.AttackerLog += PlayerProcedures.GiveXP(attacker, xpGain); } // exclude PvP score for bots if (victim.BotId == AIStatics.ActivePlayerBotId) { var score = PlayerProcedures.GetPvPScoreFromWin(attacker, victim); if (score > 0) { output.AttackerLog += PlayerProcedures.GivePlayerPvPScore(attacker, victim, score); output.VictimLog += PlayerProcedures.RemovePlayerPvPScore(victim, attacker, score); StatsProcedures.AddStat(attacker.MembershipId, StatsProcedures.Stat__DungeonPointsStolen, (float)score); } else { output.AttackerLog += $" {victim.GetFullName()} unfortunately did not have any dungeon points for you to steal for yourself."; } } // Call out a player for being the monster they are when they defeat the plush angel. if (victim.BotId == AIStatics.MinibossPlushAngelId) { output.AttackerLog += "<br><br>Why did you do that to the poor plush? They just wanted to be a friend!<br>"; output.LocationLog += $"<br><b>{attacker.GetFullName()}</b> went and bullied <b>{victim.GetFullName()}</b>, like some <b>monster</b>. The angelic plush left some flowers to the 'victor', in hope they would forgive it despite doing no wrong."; // Give the dummy a bit of madness for being a bully. EffectProcedures.GivePerkToPlayer(198, attacker); } // Heals the victorious player provided that the target was eligible if (attacker.BotId == AIStatics.ActivePlayerBotId) { // Provide no healing if the victim shared a coven with the attacker if (attacker.Covenant != null && attacker.Covenant == victim.Covenant) { output.AttackerLog += " <br>There is no glory to be had in this victory, your willpower & mana are not restored."; } else { // Figure out the modifier to be used double modifier = (levelDifference * 5) / 100; // Cap the modifier to prevent too much / too little healing. if (modifier > 0.3) { modifier = 0.3; } if (modifier < -0.55) { modifier = -0.55; } decimal healingPercent = (decimal)(0.6 + modifier); if (victim.BotId != AIStatics.ActivePlayerBotId) { // The victim is not a player, provide half of the healing. healingPercent /= 2; } // Heal the attacker and restore their Mana var healingTotal = attacker.MaxHealth * healingPercent; var manaRestoredTotal = attacker.MaxMana * healingPercent; PlayerProcedures.ChangePlayerActionMana(0, healingTotal, manaRestoredTotal, attacker.Id, false); // Remove any Self Restore entires. RemoveSelfRestore(victim); output.AttackerLog += $"<br />Invigorated by your victory and fuelled by the scattered essence that was once your foe, you are healed for {healingTotal:#} willpower and {manaRestoredTotal:#} mana."; } } output.AttackerLog += $" You collect {Math.Round(moneygain, 0)} Arpeyjis your victim dropped during the transformation."; // create inanimate XP for the victim InanimateXPProcedures.GetStruggleChance(victim, false); // if this victim is a bot, clear out some old stuff that is not needed anymore if (victim.BotId < AIStatics.ActivePlayerBotId) { AIDirectiveProcedures.DeleteAIDirectiveByPlayerId(victim.Id); PlayerLogProcedures.ClearPlayerLog(victim.Id); } TFEnergyProcedures.DeleteAllPlayerTFEnergiesOfFormSourceId(victim.Id, targetForm.Id); // if the attacker is a psycho, have them change to a new spell and equip whatever they just earned if (attacker.BotId == AIStatics.PsychopathBotId) { SkillProcedures.DeletePlayerSkill(attacker, skillSourceId); if (targetForm.MobilityType == PvPStatics.MobilityInanimate || targetForm.MobilityType == PvPStatics.MobilityPet) { if (attacker.MembershipId.IsNullOrEmpty()) { // give this bot a random replacement inanimate/pet skill var eligibleSkills = SkillStatics.GetLearnablePsychopathSkills().ToList(); var rand = new Random(); var skillToLearn = eligibleSkills.ElementAt(rand.Next(eligibleSkills.Count)); SkillProcedures.GiveSkillToPlayer(attacker.Id, skillToLearn.Id); } else { // Bot is being controlled by a player - re-add the original skill so only the ordering of skills changes SkillProcedures.GiveSkillToPlayer(attacker.Id, skillSourceId); } } } }