// Send stats for all players in all parties protected void SendAllPlayerStats() { Entity topScorerAllTeams = GameServerParty.GetTopScorerAllTeams(); foreach (var pty in GameServerParty.partyList) { var topScorerOwnTeam = pty.topScorer; foreach (Player player in pty.members) { PlayerQueueStats queueStats = player.stats.total; queueStats.secondsPlayed = secondsPlayed; queueStats.wins = (player.party == winnerParty ? 1 : 0); queueStats.losses = (player.party != winnerParty ? 1 : 0); // Calculate top scorer when not in 1v1 if (QueueSettings.queueIndex != 0) { queueStats.topScorerOwnTeam = (player == topScorerOwnTeam ? 1 : 0); queueStats.topScorerAllTeams = (player == topScorerAllTeams ? 1 : 0); } if (player.accountId != "") { // Stats StartCoroutine(ServerGameDB.SendAccountStats(player)); // Artifact rewards StartCoroutine(ServerGameDB.SendArtifactRewards(player)); } } } }
// Constructor public PlayerStats() { total = new PlayerQueueStats(); queue = new PlayerQueueStats[QueueSettings.queueCount]; for(int i = 0; i < QueueSettings.queueCount; i++) { queue[i] = new PlayerQueueStats(); } }
// Constructor public PlayerStats() { total = new PlayerQueueStats(); queue = new PlayerQueueStats[QueueSettings.queueCount]; for (int i = 0; i < QueueSettings.queueCount; i++) { queue[i] = new PlayerQueueStats(); } }
// Merges 2 queue stats void MergeQueueStats(PlayerQueueStats db, PlayerQueueStats matchStats) { db.kills += matchStats.kills; db.deaths += matchStats.deaths; db.assists += matchStats.assists; db.wins += matchStats.wins; db.losses += matchStats.losses; db.leaves += matchStats.leaves; db.hits += matchStats.hits; db.hitsTaken += matchStats.hitsTaken; db.blocks += matchStats.blocks; db.blocksTaken += matchStats.blocksTaken; db.lifeDrain += matchStats.lifeDrain; db.lifeDrainTaken += matchStats.lifeDrainTaken; db.heal += matchStats.heal; db.healTaken += matchStats.healTaken; db.damage += matchStats.damage; db.damageTaken += matchStats.damageTaken; db.cc += matchStats.cc; db.ccTaken += matchStats.ccTaken; db.runeDetonations += matchStats.runeDetonations; db.runeDetonationsTaken += matchStats.runeDetonationsTaken; db.runeDetonationsLevel += matchStats.runeDetonationsLevel; db.runeDetonationsLevelTaken += matchStats.runeDetonationsLevelTaken; db.topScorerOwnTeam += matchStats.topScorerOwnTeam; db.topScorerAllTeams += matchStats.topScorerAllTeams; db.secondsPlayed += matchStats.secondsPlayed; db.CalculateRanking(); }
// Queue statistics void DrawQueueStats(PlayerQueueStats qStats) { GUILayout.Label(" <size=50>" + qStats.ranking + "</size> points", rankingPointsStyle); using (new GUIHorizontal()) { // Left column using (new GUIVertical()) { GUILayout.Label("Wins / Losses:", statsNameStyle); GUILayout.Label(new GUIContent("Average KDA:", "Average kills / deaths / assists"), statsNameStyle); GUILayout.Label(new GUIContent("DPS:", "Damage per second"), statsNameStyle); GUILayout.Label(new GUIContent("CCPM:", "Crowd control per minute"), statsNameStyle); GUILayout.Label(new GUIContent("Damage Ratio:", "Damage / damage taken"), statsNameStyle); GUILayout.Label(new GUIContent("Hit Ratio:", "Hits / hits taken"), statsNameStyle); GUILayout.Label(new GUIContent("Block Ratio:", "Own successful blocks / enemies' successful blocks"), statsNameStyle); if (qStats.topScorerOwnTeam > 0) { GUILayout.Label("Top Scorer:", statsNameStyle); } } // Right column using (new GUIVertical()) { GUILayout.Label(qStats.wins + " / " + qStats.losses, statsStyle); GUILayout.Label(qStats.kdaString, statsStyle); GUILayout.Label(qStats.dps.ToString("0.0"), statsStyle); GUILayout.Label(qStats.ccpm.ToString("0.0"), statsStyle); GUILayout.Label(qStats.damageRatio.ToString("0.0"), statsStyle); GUILayout.Label(qStats.hitRatio.ToString("0.0"), statsStyle); GUILayout.Label(qStats.blockRatio.ToString("0.0"), statsStyle); if (qStats.topScorerOwnTeam > 0) { GUILayout.Label(GUIHelper.Plural(qStats.topScorerOwnTeam, "time"), statsStyle); } } } }
// Merges 2 queue stats void MergeQueueStats(PlayerQueueStats db, PlayerQueueStats matchStats) { db.kills += matchStats.kills; db.deaths += matchStats.deaths; db.assists += matchStats.assists; db.wins += matchStats.wins; db.losses += matchStats.losses; db.leaves += matchStats.leaves; db.hits += matchStats.hits; db.hitsTaken += matchStats.hitsTaken; db.blocks += matchStats.blocks; db.blocksTaken += matchStats.blocksTaken; db.lifeDrain += matchStats.lifeDrain; db.lifeDrainTaken += matchStats.lifeDrainTaken; db.heal += matchStats.heal; db.healTaken += matchStats.healTaken; db.damage += matchStats.damage; db.damageTaken += matchStats.damageTaken; db.cc += matchStats.cc; db.ccTaken += matchStats.ccTaken; db.runeDetonations += matchStats.runeDetonations; db.runeDetonationsTaken += matchStats.runeDetonationsTaken; db.runeDetonationsLevel += matchStats.runeDetonationsLevel; db.runeDetonationsLevelTaken += matchStats.runeDetonationsLevelTaken; db.topScorerOwnTeam += matchStats.topScorerOwnTeam; db.topScorerAllTeams += matchStats.topScorerAllTeams; db.secondsPlayed += matchStats.secondsPlayed; db.CalculateRanking(); }
// Applies damage to the player public static void ApplyDamage(Entity entity, SkillInstance skillInstance, int power) { // Dead entity or protected by spawn protection if (!entity.isAlive || entity.hasSpawnProtection || !GameManager.gameStarted) { return; } // Caster of the skill Entity caster = skillInstance.caster; // Get stats of the caster and the player PlayerQueueStats casterStats = caster.stats.total; PlayerQueueStats playerStats = entity.stats.total; // Blocked hits if (entity.blocking) { // Show blocked text if (GameManager.isClient) { if (caster == Player.main) { Entity.SpawnText(entity, "Blocked", new Color(1.0f, 0.5f, 0.0f, 1.0f)); } else if (entity == Player.main) { Entity.SpawnText(entity, "Blocked", new Color(1.0f, 0.5f, 0.0f, 1.0f), -1f, 0, Config.instance.ownDmgOffset); } } // Player blocked a hit, count them playerStats.blocks += 1; casterStats.blocksTaken += 1; // Generate threat entity.AddThreat(caster, 0); // Player blocked: Outta here. return; } // Player didn't block. // The skill used Skill skill = skillInstance.skill; Skill.Stage skillStage = skillInstance.skillStage; // Wake up player if he was sleeping and the skill is a damage skill if (power > 0 && entity.slept > 0) { entity.EndSleep(); entity.slept = 0; } // Calculate the actual damage int dmg = entity.GetModifiedDamage(power * caster.charStats.attackDmgMultiplier * caster.currentWeapon.damageMultiplier); //LogManager.General.Log("Dmg: " + dmg + ", Power: " + power); // Detonate runes if (skillStage.isRuneDetonator) { entity.DetonateRunes(caster); } // Depending on whether this is the server or client we do different stuff if (GameManager.isServer) { // Apply stagger if (skillStage.staggerDuration > 0f) { entity.networkView.RPC("Stagger", uLink.RPCMode.All, skillStage.staggerDuration); } // CC effects if (skillStage.effect != null) { entity.networkView.RPC("ReceiveSkillEffect", uLink.RPCMode.All, (byte)skillStage.effect.id, caster.id); } // Apply runes if (skillStage.runeType != Skill.RuneType.None) { byte runeId = (byte)((int)(skillStage.runeType) - 1); entity.networkView.RPC("ReceiveRune", uLink.RPCMode.All, runeId); } // Skill damage log if (entity.skillDamageReceived.ContainsKey(skill.id)) { entity.skillDamageReceived[skill.id] += dmg; } else { entity.skillDamageReceived.Add(skill.id, dmg); } // How many hits did each player do (to save assists) if (entity.hitsByPlayer.ContainsKey(caster)) { entity.hitsByPlayer[caster] += 1; } else { entity.hitsByPlayer.Add(caster, 1); } // The actual application of damage entity.health -= dmg; // Caster scored a hit. // Update the total hit counter: casterStats.hits += 1; playerStats.hitsTaken += 1; // Life drain // TODO: Only drain the actual amount of HP / damage he did if (skillStage.lifeDrainRel > 0) { int lifeDrain = (int)(dmg * skillStage.lifeDrainRel); // Life drain needs to be capped at 100% if (lifeDrain > dmg) { lifeDrain = dmg; } casterStats.lifeDrain += lifeDrain; playerStats.lifeDrainTaken += lifeDrain; caster.health += lifeDrain; } // Generate threat entity.AddThreat(caster, dmg); } else if (power != 0) { // Client shows dmg number if (caster == Player.main) { Entity.SpawnText(entity, dmg.ToString(), new Color(1.0f, 1.0f, 0.4f, 1.0f)); } else if (entity == Player.main) { Entity.SpawnText(entity, dmg.ToString(), new Color(1.0f, 0.0f, 0.0f, 1.0f), -1f, 0, Config.instance.ownDmgOffset); } // Client shows life drain heal if (skillStage.lifeDrainRel > 0 && (caster == Player.main || entity == Player.main)) { if (caster == Player.main) { Entity.SpawnText(caster, "+" + ((int)(dmg * skillStage.lifeDrainRel)), new Color(0.0f, 1.0f, 0.0f, 1.0f), -1f, 0, Config.instance.ownDmgOffset); } else if (entity == Player.main) { Entity.SpawnText(caster, "+" + ((int)(dmg * skillStage.lifeDrainRel)), new Color(0.2f, 1.0f, 0.2f, 1.0f)); } } } // Update combo counter if (caster.comboCounter != null) { caster.comboCounter.AddHit(dmg); } // Last hit entity.lastHitBy = caster; entity.lastHitBySkill = skill; caster.entityLastHit = entity; // Update CC stats if (skillStage.effect != null) { casterStats.cc += 1; playerStats.ccTaken += 1; } // Update damage stats casterStats.damage += dmg; playerStats.damageTaken += dmg; }
// Draws the score for a single player void DrawPlayerScore(Player player, int width, int height) { /*if(player == Player.main) { * GUI.backgroundColor = new Color(0.5f, 0.5f, 0.5f, 1.0f); * } else { * GUI.backgroundColor = new Color(0, 0, 0, 0); * }*/ //GUILayout.BeginHorizontal(player == Player.main ? "box" : null); //nameStyle.fixedWidth = width - columnWidth * 7 - marginX; //scoreStyle.fixedWidth = columnWidth; /*GUILayout.Label(player.GetName(), nameStyle); * GUILayout.Label(player.score.ToString(), scoreStyle); * GUILayout.Label(player.dmgDealt.ToString(), scoreStyle); * GUILayout.Label(player.ccDealt.ToString(), scoreStyle); * GUILayout.Label(player.kills.ToString(), scoreStyle); * GUILayout.Label(player.deaths.ToString(), scoreStyle); * GUILayout.Label(player.pingToServer.ToString(), scoreStyle); * GUILayout.Label(player.ranking.ToString(), scoreStyle);*/ if (player == Player.main) { GUI.Box(new Rect(0, 0, width, height), "", ownScoreLineStyle); } PlayerQueueStats stats = player.stats.total; // Name should not expand to the next column string playerName = player.name; var textDimensions = GUI.skin.label.CalcSize(new GUIContent(playerName)); if (textDimensions.x > columnWidth) { int maxNameLength = 15; if (playerName.Length > maxNameLength) { playerName = playerName.Substring(0, maxNameLength - 3) + "..."; } } GUI.Label(new Rect(marginX, 0, width - 7 * columnWidth, height), playerName, nameStyle); GUI.Label(new Rect(width - marginX - 6 * columnWidth, 0, columnWidth, height), "<b>" + player.score.ToString().HumanReadableInteger() + "</b>", scoreStyle); GUI.Label(new Rect(width - marginX - 5 * columnWidth, 0, columnWidth, height), stats.damage.ToString().HumanReadableInteger(), scoreStyle); GUI.Label(new Rect(width - marginX - 4 * columnWidth, 0, columnWidth, height), stats.cc.ToStringLookup().HumanReadableInteger(), scoreStyle); GUI.Label(new Rect(width - marginX - 3 * columnWidth, 0, columnWidth, height), string.Concat(stats.kills.ToStringLookup(), " / ", stats.deaths.ToStringLookup(), " / ", stats.assists.ToStringLookup()), scoreStyle); GUI.Label(new Rect(width - marginX - 2 * columnWidth, 0, columnWidth, height), player.stats.ping.ToStringLookup().HumanReadableInteger(), scoreStyle); // Ranking change string rankingBonus = ""; if (player.newBestRanking != -1) { int rankingDiff = player.newBestRanking - player.stats.bestRanking; if (rankingDiff > 0) { rankingBonus = " <color=green>+" + rankingDiff.ToStringLookup() + "</color>"; } else if (rankingDiff < 0) { rankingBonus = " <color=red>" + rankingDiff.ToStringLookup() + "</color>"; } } GUI.Label(new Rect(width - marginX - columnWidth, 0, columnWidth, height), player.stats.bestRanking.ToString() + rankingBonus, scoreStyle); //GUILayout.EndHorizontal(); }
// Read a single value from JSON public static object ReadJSONValue(Jboy.JsonReader reader, FieldInfo field) { var fieldType = field.FieldType; if (fieldType == typeof(int)) { return((int)(reader.ReadNumber())); } else if (fieldType == typeof(uint)) { return((uint)(reader.ReadNumber())); } else if (fieldType == typeof(long)) { return((long)(reader.ReadNumber())); } else if (fieldType == typeof(byte)) { return((byte)(reader.ReadNumber())); } else if (fieldType == typeof(double)) { return(reader.ReadNumber()); } else if (fieldType == typeof(float)) { return((float)reader.ReadNumber()); } else if (fieldType == typeof(KeyCode)) { return((KeyCode)(reader.ReadNumber())); } else if (fieldType == typeof(string)) { string stringObject; if (reader.TryReadString(out stringObject)) { return(stringObject); } else { reader.ReadNull(); return(null); } } else if (fieldType == typeof(int[])) { return(Jboy.Json.ReadObject <int[]>(reader)); } else if (fieldType == typeof(Color)) { return(ColorSerializer.JsonDeserializer(reader)); } else if (fieldType == typeof(ServerType)) { return(ServerTypeSerializer.JsonDeserializer(reader)); } else if (fieldType == typeof(PlayerQueueStats)) { return(GenericSerializer.ReadJSONClassInstance <PlayerQueueStats>(reader)); } else if (fieldType == typeof(PlayerQueueStats[])) { reader.ReadArrayStart(); PlayerQueueStats[] valArray = new PlayerQueueStats[QueueSettings.queueCount]; for (int i = 0; i < QueueSettings.queueCount; i++) { valArray[i] = GenericSerializer.ReadJSONClassInstance <PlayerQueueStats>(reader); } reader.ReadArrayEnd(); return(valArray); } else if (fieldType == typeof(InputControl[])) { reader.ReadArrayStart(); List <InputControl> valList = new List <InputControl>(); while (true) { try { valList.Add(GenericSerializer.ReadJSONClassInstance <InputControl>(reader)); } catch { break; } } reader.ReadArrayEnd(); return(valList.ToArray()); } else if (fieldType == typeof(Artifact)) { return(Jboy.Json.ReadObject <Artifact>(reader)); } else if (fieldType == typeof(ArtifactSlot)) { return(Jboy.Json.ReadObject <ArtifactSlot>(reader)); } else if (fieldType == typeof(ArtifactTree)) { return(Jboy.Json.ReadObject <ArtifactTree>(reader)); } else if (fieldType == typeof(ArtifactInventory)) { return(Jboy.Json.ReadObject <ArtifactInventory>(reader)); } else if (fieldType == typeof(List <ItemSlot>)) { return(Jboy.Json.ReadObject <List <ItemSlot> >(reader)); } else if (fieldType == typeof(TimeStamp)) { return(Jboy.Json.ReadObject <TimeStamp>(reader)); } else if (fieldType == typeof(SkillBuild)) { return(Jboy.Json.ReadObject <SkillBuild>(reader)); //} else if(fieldType == typeof(WeaponBuild)) { // return Jboy.Json.ReadObject<WeaponBuild>(reader); //} else if(fieldType == typeof(AttunementBuild)) { // return Jboy.Json.ReadObject<AttunementBuild>(reader); } else if (fieldType == typeof(WeaponBuild[])) { return(Jboy.Json.ReadObject <WeaponBuild[]>(reader)); } else if (fieldType == typeof(AttunementBuild[])) { return(Jboy.Json.ReadObject <AttunementBuild[]>(reader)); } else if (fieldType == typeof(Guild)) { return(GenericSerializer.ReadJSONClassInstance <Guild>(reader)); } else if (fieldType == typeof(GuildMember)) { return(GenericSerializer.ReadJSONClassInstance <GuildMember>(reader)); } else if (fieldType == typeof(GuildMember[])) { return(Jboy.Json.ReadObject <GuildMember[]>(reader)); } else if (fieldType == typeof(List <string>)) { return(Jboy.Json.ReadObject <List <string> >(reader)); } else if (fieldType == typeof(List <Friend>)) { return(Jboy.Json.ReadObject <List <Friend> >(reader)); } else if (fieldType == typeof(List <FriendsGroup>)) { return(Jboy.Json.ReadObject <List <FriendsGroup> >(reader)); } else if (fieldType == typeof(Texture2D)) { return(Texture2DSerializer.JsonDeserializer(reader)); } else { LogManager.General.LogError("Unknown field type for GenericSerializer.ReadJSONValue: " + fieldType); return((int)(reader.ReadNumber())); } }