Merge remote-tracking branch 'origin/main'

# Conflicts:
#	static/filterWeapons.js
#	static/operative.json
This commit is contained in:
IM23a-spirgif
2025-01-22 13:24:05 +01:00
11 changed files with 2451 additions and 203 deletions
+1 -30
View File
@@ -3,42 +3,12 @@ import json
app = Flask(__name__)
# Load the data from the JSON file
with open('static/data.json') as f:
guns = json.load(f)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/api/guns', methods=['GET'])
def get_guns():
updated_guns = []
for gun in guns:
original_damage = gun['damage']
# Calculate RPS, DPS, DPM, avgDPS
rps = gun['rpm'] / 60
dps = original_damage * rps
reload_time_min = gun['reload_time'] / 60
dpm = (gun['mag_size'] * original_damage) / (reload_time_min + (gun['mag_size'] / gun['rpm']))
avg_dps = dpm / 60
total_damage = original_damage * gun['damage_multiplier']
# Add calculated stats to the gun data
gun.update({
'total_damage': total_damage,
'rps': rps,
'dps': dps,
'dpm': dpm,
'avg_dps': avg_dps
})
updated_guns.append(gun)
return jsonify(updated_guns)
@app.route('/calculator')
def calculator():
return render_template('calculator.html')
@@ -53,5 +23,6 @@ def about_us():
def suggestion():
return render_template('suggestion.html')
if __name__ == '__main__':
app.run(debug=True)
+128 -98
View File
@@ -2,52 +2,52 @@
{
"id": 1,
"name": "G18",
"damage": 32,
"damage": 34,
"damage_multiplier": 1,
"rpm": 550,
"mag_size": 18,
"rpm": 800,
"mag_size": 17,
"reload_time": 2,
"guntype": "PISTOL"
"guntype": ["PISTOL", "SECONDARY"]
},
{
"id": 2,
"name": "M1911",
"damage": 37,
"damage": 45,
"damage_multiplier": 1,
"rpm": 580,
"mag_size": 8,
"reload_time": 1.15,
"guntype": "PISTOL"
"guntype": ["PISTOL", "SECONDARY", "WW2"]
},
{
"id": 3,
"name": "M9A",
"damage": 31,
"damage": 65,
"damage_multiplier": 1,
"rpm": 850,
"rpm": 300,
"mag_size": 15,
"reload_time": 2,
"guntype": "PISTOL"
"guntype": ["PISTOL", "SECONDARY"]
},
{
"id": 4,
"name": "M1911MK2",
"damage": 48,
"damage": 60,
"damage_multiplier": 1,
"rpm": 720,
"mag_size": 16,
"reload_time": 3,
"guntype": "PISTOL"
"guntype": ["PISTOL", "SECONDARY"]
},
{
"id": 5,
"name": "Luger",
"damage": 58,
"damage": 150,
"damage_multiplier": 1,
"rpm": 500,
"mag_size": 8,
"reload_time": 1.95,
"guntype": "PISTOL"
"guntype": ["PISTOL", "WW2", "SECONDARY"]
},
{
"id": 6,
@@ -57,7 +57,7 @@
"rpm": 600,
"mag_size": 30,
"reload_time": 2.1,
"guntype": "RIFLE"
"guntype": ["RIFLE", "PRIMARY","SOVIET"]
},
{
"id": 7,
@@ -67,7 +67,7 @@
"rpm": 700,
"mag_size": 30,
"reload_time": 2.4,
"guntype": "RIFLE"
"guntype": ["RIFLE", "PRIMARY"]
},
{
"id": 8,
@@ -77,7 +77,7 @@
"rpm": 400,
"mag_size": 24,
"reload_time": 2.6,
"guntype": "RIFLE"
"guntype": ["RIFLE", "SEMI-AUTO", "PRIMARY"]
},
{
"id": 9,
@@ -87,7 +87,7 @@
"rpm": 670,
"mag_size": 30,
"reload_time": 3.25,
"guntype": "RIFLE"
"guntype": ["RIFLE", "PRIMARY"]
},
{
"id": 10,
@@ -97,7 +97,7 @@
"rpm": 700,
"mag_size": 30,
"reload_time": 2.35,
"guntype": "RIFLE"
"guntype": ["RIFLE", "PRIMARY"]
},
{
"id": 11,
@@ -107,7 +107,7 @@
"rpm": 60,
"mag_size": 8,
"reload_time": 2.8,
"guntype": "RIFLE"
"guntype": ["RIFLE", "SEMI-AUTO", "PRIMARY"]
},
{
"id": 12,
@@ -117,7 +117,17 @@
"rpm": 70,
"mag_size": 12,
"reload_time": 12,
"guntype": "SHOTGUN"
"guntype": ["SHOTGUN", "PRIMARY"]
},
{
"id": 87,
"name": "R870-B",
"damage": 92,
"damage_multiplier": 6,
"rpm": 70,
"mag_size": 12,
"reload_time": 12,
"guntype": ["SHOTGUN", "PRIMARY"]
},
{
"id": 14,
@@ -126,18 +136,18 @@
"damage_multiplier": 4,
"rpm": 300,
"mag_size": 7,
"reload_time": 4,
"guntype": "SHOTGUN"
"reload_time": 4.5,
"guntype": ["SHOTGUN", "PRIMARY"]
},
{
"id": 16,
"name": "Shorty",
"damage": 29,
"damage": 40,
"damage_multiplier": 4,
"rpm": 185,
"rpm": 150,
"mag_size": 8,
"reload_time": 3.5,
"guntype": "SHOTGUN"
"guntype": ["SHOTGUN", "SECONDARY"]
},
{
"id": 18,
@@ -147,7 +157,7 @@
"rpm": 300,
"mag_size": 20,
"reload_time": 2.2,
"guntype": "SHOTGUN"
"guntype": ["SHOTGUN", "PRIMARY"]
},
{
"id": 20,
@@ -157,7 +167,7 @@
"rpm": 900,
"mag_size": 50,
"reload_time": 3,
"guntype": "SMG"
"guntype": ["SMG", "PRIMARY"]
},
{
"id": 21,
@@ -167,17 +177,17 @@
"rpm": 750,
"mag_size": 50,
"reload_time": 2.5,
"guntype": "SMG"
"guntype": ["SMG", "PRIMARY", "WW2"]
},
{
"id": 22,
"name": "Uzi",
"damage": 20,
"damage": 32,
"damage_multiplier": 1,
"rpm": 850,
"mag_size": 32,
"rpm": 950,
"mag_size": 20,
"reload_time": 2,
"guntype": "SMG"
"guntype": ["SMG", "SECONDARY"]
},
{
"id": 23,
@@ -187,67 +197,67 @@
"rpm": 1050,
"mag_size": 33,
"reload_time": 2,
"guntype": "SMG"
"guntype": ["SMG", "PRIMARY"]
},
{
"id": 24,
"name": "MP5",
"damage": 23,
"damage": 26,
"damage_multiplier": 1,
"rpm": 800,
"mag_size": 30,
"reload_time": 2.1,
"guntype": "SMG"
"guntype": ["SMG", "SECONDARY"]
},
{
"id": 25,
"name": "U10",
"damage": 18,
"damage": 22,
"damage_multiplier": 1,
"rpm": 750,
"mag_size": 65,
"reload_time": 2,
"guntype": "SMG"
"guntype": ["SMG", "SECONDARY"]
},
{
"id": 26,
"name": "MPX",
"damage": 28,
"damage": 36,
"damage_multiplier": 1,
"rpm": 780,
"mag_size": 30,
"reload_time": 2.65,
"guntype": "SMG"
"guntype": ["SMG", "SECONDARY"]
},
{
"id": 27,
"name": "UMP45",
"damage": 28,
"damage": 36,
"damage_multiplier": 1,
"rpm": 600,
"mag_size": 25,
"reload_time": 2,
"guntype": "SMG"
"guntype": ["SMG", "SECONDARY"]
},
{
"id": 28,
"name": "Prototype",
"damage": 21,
"damage": 28,
"damage_multiplier": 1,
"rpm": 800,
"mag_size": 25,
"reload_time": 2.5,
"guntype": "SMG"
"guntype": ["SMG", "SECONDARY"]
},
{
"id": 29,
"name": "Prototype (Overcharged)",
"damage": 21,
"damage": 28,
"damage_multiplier": 1.35,
"rpm": 800,
"mag_size": 25,
"reload_time": 2.5,
"guntype": "SMG"
"guntype": ["SMG", "SECONDARY"]
},
{
"id": 30,
@@ -257,7 +267,7 @@
"rpm": 550,
"mag_size": 32,
"reload_time": 3,
"guntype": "SMG"
"guntype": ["SMG", "PRIMARY", "WW2"]
},
{
"id": 31,
@@ -267,7 +277,7 @@
"rpm": 750,
"mag_size": 100,
"reload_time": 5.5,
"guntype": "LMG"
"guntype": ["LMG", "PRIMARY","SOVIET"]
},
{
"id": 32,
@@ -277,7 +287,7 @@
"rpm": 850,
"mag_size": 100,
"reload_time": 6,
"guntype": "LMG"
"guntype": ["LMG", "PRIMARY"]
},
{
"id": 33,
@@ -287,7 +297,7 @@
"rpm": 780,
"mag_size": 125,
"reload_time": 5.5,
"guntype": "LMG"
"guntype": ["LMG", "PRIMARY"]
},
{
"id": 34,
@@ -297,7 +307,7 @@
"rpm": 700,
"mag_size": 50,
"reload_time": 3.25,
"guntype": "RIFLE"
"guntype": ["RIFLE", "PRIMARY"]
},
{
"id": 35,
@@ -307,7 +317,7 @@
"rpm": 850,
"mag_size": 125,
"reload_time": 5.5,
"guntype": "LMG"
"guntype": ["LMG", "PRIMARY"]
},
{
"id": 36,
@@ -317,7 +327,7 @@
"rpm": 750,
"mag_size": 50,
"reload_time": 3.25,
"guntype": "RIFLE"
"guntype": ["RIFLE", "PRIMARY"]
},
{
"id": 37,
@@ -327,7 +337,7 @@
"rpm": 30,
"mag_size": 5,
"reload_time": 3.5,
"guntype": "RIFLE?"
"guntype": ["RIFLE", "SEMI-AUTO", "PRIMARY"]
},
{
"id": 38,
@@ -337,7 +347,7 @@
"rpm": 800,
"mag_size": 50,
"reload_time": 2.5,
"guntype": "SMG"
"guntype": ["SMG", "PRIMARY"]
},
{
"id": 39,
@@ -347,7 +357,7 @@
"rpm": 900,
"mag_size": 64,
"reload_time": 4,
"guntype": "SMG"
"guntype": ["SMG", "PRIMARY"]
},
{
"id": 40,
@@ -357,7 +367,7 @@
"rpm": 1000,
"mag_size": 50,
"reload_time": 2.45,
"guntype": "RIFLE"
"guntype": ["RIFLE", "PRIMARY"]
},
{
"id": 41,
@@ -367,7 +377,7 @@
"rpm": 3000,
"mag_size": 10000000000000000000,
"reload_time": 0,
"guntype": "SPECIAL"
"guntype": ["SPECIAL"]
},
{
"id": 42,
@@ -377,7 +387,7 @@
"rpm": 500,
"mag_size": 650,
"reload_time": 0,
"guntype": "SPECIAL"
"guntype": ["SPECIAL"]
},
{
"id": 43,
@@ -387,7 +397,7 @@
"rpm": 300,
"mag_size": 650,
"reload_time": 0,
"guntype": "SPECIAL"
"guntype": ["SPECIAL"]
},
{
"id": 44,
@@ -397,7 +407,17 @@
"rpm": 650,
"mag_size": 18,
"reload_time": 2,
"guntype": "PISTOL"
"guntype": ["PISTOL"]
},
{
"id": 89,
"name": "Improved G18 (150+ Kills)",
"damage": 51,
"damage_multiplier": 1,
"rpm": 650,
"mag_size": 23,
"reload_time": 2,
"guntype": ["PISTOL"]
},
{
"id": 45,
@@ -407,7 +427,7 @@
"rpm": 550,
"mag_size": 18,
"reload_time": 2,
"guntype": "PISTOL"
"guntype": ["PISTOL"]
},
{
"id": 46,
@@ -417,7 +437,7 @@
"rpm": 225,
"mag_size": 10,
"reload_time": 5,
"guntype": "SHOTGUN"
"guntype": ["SHOTGUN", "PRIMARY"]
},
{
"id": 48,
@@ -427,7 +447,7 @@
"rpm": 550,
"mag_size": 30,
"reload_time": 2.35,
"guntype": "RIFLE"
"guntype": ["RIFLE", "PRIMARY"]
},
{
"id": 49,
@@ -437,7 +457,7 @@
"rpm": 600,
"mag_size": 30,
"reload_time": 2.35,
"guntype": "RIFLE"
"guntype": ["RIFLE", "PRIMARY"]
},
{
"id": 50,
@@ -447,7 +467,7 @@
"rpm": 600,
"mag_size": 32,
"reload_time": 2.45,
"guntype": "RIFLE"
"guntype": ["RIFLE", "PRIMARY"]
},
{
"id": 51,
@@ -457,7 +477,7 @@
"rpm": 650,
"mag_size": 32,
"reload_time": 2.45,
"guntype": "RIFLE"
"guntype": ["RIFLE", "PRIMARY"]
},
{
"id": 52,
@@ -467,7 +487,7 @@
"rpm": 625,
"mag_size": 100,
"reload_time": 4.5,
"guntype": "LMG"
"guntype": ["LMG", "PRIMARY"]
},
{
"id": 53,
@@ -477,17 +497,17 @@
"rpm": 700,
"mag_size": 100,
"reload_time": 4.5,
"guntype": "LMG"
"guntype": ["LMG", "PRIMARY"]
},
{
"id": 54,
"name": "Improved P90",
"damage": 32,
"damage": 34,
"damage_multiplier": 1,
"rpm": 800,
"mag_size": 50,
"reload_time": 2.6,
"guntype": "SMG"
"guntype": ["SMG", "PRIMARY"]
},
{
"id": 55,
@@ -497,7 +517,7 @@
"rpm": 550,
"mag_size": 32,
"reload_time": 2.5,
"guntype": "SMG"
"guntype": ["SMG", "PRIMARY", "WW2"]
},
{
"id": 56,
@@ -507,7 +527,7 @@
"rpm": 700,
"mag_size": 34,
"reload_time": 3.5,
"guntype": "PISTOL"
"guntype": ["PISTOL"]
},
{
"id": 57,
@@ -517,7 +537,7 @@
"rpm": 440,
"mag_size": 18,
"reload_time": 3.5,
"guntype": "RIFLE"
"guntype": ["RIFLE", "SEMI-AUTO", "PRIMARY"]
},
{
"id": 58,
@@ -527,7 +547,7 @@
"rpm": 540,
"mag_size": 18,
"reload_time": 3.5,
"guntype": "RIFLE"
"guntype": ["RIFLE", "SEMI-AUTO", "PRIMARY"]
},
{
"id": 59,
@@ -537,7 +557,7 @@
"rpm": 780,
"mag_size": 30,
"reload_time": 2.25,
"guntype": "RIFLE"
"guntype": ["RIFLE", "PRIMARY"]
},
{
"id": 60,
@@ -547,7 +567,7 @@
"rpm": 900,
"mag_size": 26,
"reload_time": 2.5,
"guntype": "SMG?"
"guntype": ["PISTOL"]
},
{
"id": 61,
@@ -557,7 +577,7 @@
"rpm": 1200,
"mag_size": 26,
"reload_time": 2,
"guntype": "SMG?"
"guntype": ["PISTOL"]
},
{
"id": 62,
@@ -567,7 +587,7 @@
"rpm": 800,
"mag_size": 30,
"reload_time": 1.5,
"guntype": "SMG"
"guntype": ["SMG", "PRIMARY"]
},
{
"id": 63,
@@ -587,7 +607,17 @@
"rpm": 1050,
"mag_size": 30,
"reload_time": 2,
"guntype": "SMG"
"guntype": ["SMG", "PRIMARY"]
},
{
"id": 88,
"name": "Improved Vector (150+ Kills)",
"damage": 39,
"damage_multiplier": 1,
"rpm": 1050,
"mag_size": 33,
"reload_time": 2,
"guntype": ["SMG", "PRIMARY"]
},
{
"id": 65,
@@ -597,7 +627,7 @@
"rpm": 850,
"mag_size": 30,
"reload_time": 2,
"guntype": "SMG"
"guntype": ["SMG", "PRIMARY"]
},
{
"id": 66,
@@ -607,7 +637,7 @@
"rpm": 850,
"mag_size": 30,
"reload_time": 2,
"guntype": "SMG"
"guntype": ["SMG", "PRIMARY"]
},
{
"id": 67,
@@ -637,7 +667,7 @@
"rpm": 830,
"mag_size": 30,
"reload_time": 2.5,
"guntype": "RIFLE"
"guntype": ["RIFLE", "PRIMARY"]
},
{
"id": 70,
@@ -647,7 +677,7 @@
"rpm": 900,
"mag_size": 30,
"reload_time": 2.5,
"guntype": "RIFLE"
"guntype": ["RIFLE", "PRIMARY"]
},
{
"id": 71,
@@ -667,7 +697,7 @@
"rpm": 700,
"mag_size": 30,
"reload_time": 3.25,
"guntype": "RIFLE"
"guntype": ["RIFLE", "PRIMARY"]
},
{
"id": 73,
@@ -677,7 +707,7 @@
"rpm": 400,
"mag_size": 18,
"reload_time": 2.1,
"guntype": "PISTOL"
"guntype": ["PISTOL", "DEAGLE"]
},
{
"id": 74,
@@ -687,7 +717,7 @@
"rpm": 400,
"mag_size": 36,
"reload_time": 3.5,
"guntype": "PISTOL"
"guntype": ["PISTOL", "DEAGLE"]
},
{
"id": 75,
@@ -697,7 +727,7 @@
"rpm": 300,
"mag_size": 10,
"reload_time": 3,
"guntype": "RIFLE"
"guntype": ["RIFLE", "PRIMARY", "SEMI-AUTO"]
},
{
"id": 76,
@@ -707,7 +737,7 @@
"rpm": 700,
"mag_size": 10,
"reload_time": 2,
"guntype": "RIFLE?"
"guntype": "RIFLE"
},
{
"id": 77,
@@ -717,7 +747,7 @@
"rpm": 1000,
"mag_size": 71,
"reload_time": 2.5,
"guntype": "UNKOWN"
"guntype": ["SMG", "PRIMARY", "SOVIET"]
},
{
"id": 78,
@@ -727,7 +757,7 @@
"rpm": 690,
"mag_size": 30,
"reload_time": 2.5,
"guntype": "RIFLE"
"guntype": ["RIFLE", "PRIMARY", "SOVIET"]
},
{
"id": 79,
@@ -737,7 +767,7 @@
"rpm": 800,
"mag_size": 64,
"reload_time": 4,
"guntype": "SMG"
"guntype": ["SMG"]
},
{
"id": 80,
@@ -747,7 +777,7 @@
"rpm": 800,
"mag_size": 60,
"reload_time": 4,
"guntype": "SMG"
"guntype": ["SMG"]
},
{
"id": 81,
@@ -757,7 +787,7 @@
"rpm": 800,
"mag_size": 50,
"reload_time": 2.5,
"guntype": "SMG"
"guntype": ["SMG", "PRIMARY"]
},
{
"id": 82,
@@ -767,7 +797,7 @@
"rpm": 400,
"mag_size": 12,
"reload_time": 2.6,
"guntype": "RIFLE"
"guntype": ["RIFLE"]
},
{
"id": 83,
@@ -777,7 +807,7 @@
"rpm": 150,
"mag_size": 8,
"reload_time": 2.2,
"guntype": "SHOTGUN"
"guntype": ["SHOTGUN", "PRIMARY"]
},
{
"id": 84,
@@ -787,7 +817,7 @@
"rpm": 200,
"mag_size": 1000000000000000000000000000000000000000000000000000000000000000,
"reload_time": 0,
"guntype": "SHOTGUN"
"guntype": ["SHOTGUN", "PRIMARY"]
},
{
"id": 85,
@@ -797,7 +827,7 @@
"rpm": 900,
"mag_size": 30,
"reload_time": 4,
"guntype": "RIFLE"
"guntype": ["RIFLE", "PRIMARY"]
},
{
"id": 86,
@@ -807,6 +837,6 @@
"rpm": 9999,
"mag_size": 999,
"reload_time": 1,
"guntype": "RIFLE"
"guntype": ["RIFLE", "PRIMARY"]
}
]
@@ -4,25 +4,29 @@
"id": "damage-item-additive-elite-he-rounds",
"label": "Elite HE Rounds (+14 damage)",
"value": 14,
"type": "additive"
"type": "additive",
"operatives": ""
},
{
"id": "damage-item-additive-he-rounds",
"label": "HE Rounds (+8 damage)",
"value": 8,
"type": "additive"
"type": "additive",
"operatives": ""
},
{
"id": "damage-item-multiplicative-strength-mixture",
"label": "Strength Mixture (+20% damage)",
"value": 1.2,
"type": "multiplicative"
"type": "multiplicative",
"operatives": ""
},
{
"id": "damage-item-multiplicative-fortunos-necklace",
"label": "Fortunos Necklace (+15% damage)",
"value": 1.15,
"type": "multiplicative"
"type": "multiplicative",
"operatives": ""
},
{
"id": "multiple-buffs-bloxy-cola",
@@ -38,19 +42,22 @@
"value": 0,
"buffType": "multiplicative"
}
]
],
"operatives": ""
},
{
"id": "damage-item-multiplicative-enhancer",
"label": "Enhancer (+10% damage)",
"value": 1.1,
"type": "multiplicative"
"type": "multiplicative",
"operatives": ""
},
{
"id": "damage-item-multiplicative-teleport-device",
"label": "Teleport Device (+25% damage)",
"value": 1.25,
"type": "multiplicative"
"type": "multiplicative",
"operatives": ""
}
],
"operativePerks": [
@@ -58,25 +65,35 @@
"id": "damage-perk-multiplicative-fbi-badge",
"label": "FBI Badge (+10% Damage)",
"value": 1.1,
"type": "multiplicative"
"type": "multiplicative",
"operatives": "UIU"
},
{
"id": "damage-perk-multiplicative-anatomy-book",
"label": "Anatomy Book (+5% Damage)",
"value": 1.05,
"type": "multiplicative"
"type": "multiplicative",
"operatives": ""
},
{
"id": "damage-perk-multiplicative-silly-soldier",
"label": "Silly Soldier (+10% Damage)",
"value": 1.10,
"type": "multiplicative"
"type": "multiplicative",
"operatives": ""
},
{
"id": "damage-perk-multiplicative-precise-shots",
"label": "Precise Shots (+15% Damage)",
"buffs": [
{
"type": "damage",
"value": 1.15,
"type": "multiplicative"
"buffType": "multiplicative-headshot"
}
],
"appliesTo": "",
"operatives": ""
},
{
"id": "damage-perk-multiplicative-goc-insignia",
@@ -92,10 +109,23 @@
"value": 0.85,
"buffType": "multiplicative"
}
]
],
"operatives": "GOC"
}
],
"abilityPerks": [
{
"id": "headshot-damage-buff",
"label": "[All Operatives] Headshot (+25% Damage)",
"buffs": [
{
"type": "damage",
"value": 1.25,
"buffType": "multiplicative-headshot-base"
}
],
"appliesTo": ""
},
{
"id": "multiple-buffs-firefight",
"label": "[All Operatives] Firefight (+35% Damage, +40% Reload Speed)",
@@ -110,17 +140,22 @@
"value": 0.6,
"buffType": "multiplicative"
}
]
],
"operatives": "",
"appliesTo": ""
},
{
"id": "damage-ability-multiplicative-heath-spawn",
"label": "[All Operatives] Heath Spawn (+30% Damage)",
"value": 1.3,
"type": "multiplicative"
"type": "multiplicative",
"operatives": "",
"appliesTo": ""
},
{
"id": "multiple-buffs-warcry",
"label": "[All Operatives] War Cry(+25% Damage, +?% Reload Speed)",
"operatives": "",
"buffs": [
{
"type": "damage",
@@ -132,37 +167,125 @@
"value": 1,
"buffType": "multiplicative"
}
]
],
"appliesTo": ""
},
{
"id": "reload-buff-focus-fire",
"label": "[All Operatives] Focus Fire (+20% Reload Speed)",
"buffs": [
{
"type": "reloadTime",
"value": 0.8,
"buffType": "multiplicative"
}
],
"operatives": "",
"appliesTo": ""
},
{
"id": "damage-ability-multiplicative-blackout",
"label": "[All Operatives] Blackout (+30% Damage)",
"value": 1.3,
"type": "multiplicative"
"type": "multiplicative",
"operatives": "",
"appliesTo": ""
},
{
"id": "damage-ability-demoman",
"label": "[All Operatives] Enemy hit by Demolitionist Explosive (+15% Damage)",
"value": 1.15,
"type": "multiplicative",
"operatives": "",
"appliesTo": ""
},
{
"id": "damage-ability-multiplicative-red-scan",
"label": "[All Operatives] Red Scan (+30% Damage)",
"value": 1.3,
"type": "multiplicative"
"type": "multiplicative",
"operatives": "",
"appliesTo": ""
},
{
"id": "damage-ability-multiplicative-red-scan",
"label": "[All Operatives] Green Scan (+50% Damage)",
"value": 1.5,
"type": "multiplicative"
"type": "multiplicative",
"operatives": "",
"appliesTo": ""
},
{
"id": "damage-ability-multiplicative-point-out",
"label": "[All Operatives] Point Out (+50% Damage)",
"value": 1.5,
"type": "multiplicative"
"type": "multiplicative",
"operatives": "",
"appliesTo": ""
},
{
"id": "damage-item-additive-5-uiu-elite",
"label": "[All Operatives] 5 UIU Elite nearby (+25 damage)",
"value": 25,
"type": "additive"
"type": "additive",
"operatives": "",
"appliesTo": ""
},
{
"id": "damage-item-additive-field-support",
"label": "[All Operatives] MTF Commander Field Support (+8 damage)",
"value": 8,
"type": "additive",
"operatives": "",
"appliesTo": ""
},
{
"id": "damage-ability-multiplicative-scan grenade",
"label": "[All Operatives] Scan Grenade (+15% Damage)",
"value": 1.15,
"type": "multiplicative",
"operatives": "",
"appliesTo": ""
},
{
"id": "damage-upgrade-multiplicative-upgraded-bullets",
"label": "[All Operatives] Experimental Bullets (+30% Damage)",
"value": 1.3,
"type": "multiplicative",
"operatives": "",
"appliesTo": ""
},
{
"id": "damage-item-additive-GOC",
"label": "[All Operatives] GOC Ally (+8 damage)",
"value": 8,
"type": "additive",
"operatives": "",
"appliesTo": ""
},
{
"id": "damage-item-additive-GOC-1",
"label": "[All Operatives] Weak Points (+8 damage)",
"value": 8,
"type": "additive",
"operatives": "",
"appliesTo": ""
},
{
"id": "damage-item-additive-GOC-3",
"label": "[All Operatives] GOC Ally: Kraken Buff (+3 damage)",
"value": 3,
"type": "additive",
"operatives": "",
"appliesTo": ""
},
{
"id": "damage-item-additive-uiu-1",
"label": "[All Operatives] UIU Upgraded Towers (+10% damage)",
"value": 1.1,
"type": "multiplicative",
"operatives": "",
"appliesTo": ""
}
]
}
File diff suppressed because it is too large Load Diff
+31 -13
View File
@@ -1,8 +1,28 @@
document.addEventListener('DOMContentLoaded', () => {
fetch('/api/guns')
fetch('/static/json/data.json') // Fetch the JSON file directly
.then(response => response.json())
.then(data => {
populateTable(data);
const updatedGuns = data.map(gun => {
const original_damage = gun['damage'];
const total_damage = original_damage * gun['damage_multiplier'];
const rps = gun['rpm'] / 60;
const dps = total_damage * rps;
const reload_time_min = gun['reload_time'] / 60;
const dpm = (gun['mag_size'] * total_damage) / (reload_time_min + (gun['mag_size'] / gun['rpm']));
const avg_dps = dpm / 60;
// Add the calculated stats to the gun object
return {
...gun,
total_damage: total_damage,
rps: rps,
dps: dps,
dpm: dpm,
avg_dps: avg_dps
};
});
populateTable(updatedGuns);
});
});
@@ -11,16 +31,14 @@ function populateTable(data) {
table.innerHTML = ''; // Clear existing table data
data.forEach(gun => {
const row = table.insertRow();
row.insertCell(0).innerText = gun.id;
row.insertCell(1).innerText = gun.name;
row.insertCell(2).innerText = gun.total_damage;
row.insertCell(3).innerText = gun.rpm;
row.insertCell(4).innerText = gun.mag_size;
row.insertCell(5).innerText = gun.reload_time;
row.insertCell(6).innerText = gun.guntype;
row.insertCell(7).innerText = gun.rps.toFixed(2);
row.insertCell(8).innerText = gun.dps.toFixed(2);
row.insertCell(9).innerText = gun.dpm.toFixed(2);
row.insertCell(10).innerText = gun.avg_dps.toFixed(2);
row.insertCell(0).innerText = gun.name;
row.insertCell(1).innerText = gun.total_damage.toFixed(2);
row.insertCell(2).innerText = gun.rpm;
row.insertCell(3).innerText = gun.mag_size;
row.insertCell(4).innerText = gun.reload_time;
row.insertCell(5).innerText = gun.rps.toFixed(2);
row.insertCell(6).innerText = gun.dps.toFixed(2);
row.insertCell(7).innerText = gun.dpm.toFixed(2);
row.insertCell(8).innerText = gun.avg_dps.toFixed(2);
});
}
+158 -1
View File
@@ -1,9 +1,34 @@
input[type="text"] {
width: 100%;
padding: 8px;
margin: 10px 0;
box-sizing: border-box;
font-size: 16px;
}
#modifiers-container {
display: flex;
justify-content: space-between; /* Distribute space between the items */
flex-wrap: wrap; /* Allow wrapping to avoid overflow */
}
/* Style for the modifiers section */
#modifiers {
display: flex; /* Use flexbox for alignment */
flex-direction: column; /* Stack items vertically */
width: 50%;
}
#abilities {
width: 42.5%; /* Adjust this value as needed */
}
body {
background-image: url("/static/img/trlbg1.jpg");
background-repeat: no-repeat;
background-attachment: fixed;
background-size: cover;
position: relative; /* This allows the z-index on children elements to work */
position: relative;
z-index: -1; /* Send the background behind the content */
font-family: Arial, sans-serif;
margin: 20px;
@@ -229,3 +254,135 @@ nav {
.button1 {
background-color: black;
}
/* Suggestion Form Enhancements */
main h1 {
font-size: 2.5em;
color: black;
text-align: center;
margin-bottom: 20px;
}
.suggestion-title {
font-size: 1.5em;
color: black;
text-align: center;
margin-bottom: 30px;
}
article label {
font-weight: bold;
font-size: 1.1em;
color: #333;
margin-bottom: 10px;
display: block;
}
input[type="text"], input[type="number"], textarea {
width: 95%;
padding: 12px;
font-size: 1em;
border: 1px solid #ccc;
border-radius: 8px;
margin-bottom: 20px;
background-color: #f9f9f9;
transition: border-color 0.3s, box-shadow 0.3s;
}
/* Focus effect to highlight the active input field */
input[type="text"]:focus, input[type="number"]:focus, textarea:focus {
border-color: black;
box-shadow: 0 0 5px darkred;
background-color: #fff;
outline: none;
}
textarea {
resize: none;
height: 150px;
}
/* Submit button improvements */
.button1 {
background-color: darkred;
color: white;
font-size: 1.2em;
padding: 12px 24px;
border: none;
border-radius: 8px;
cursor: pointer;
display: block;
margin: 0 auto;
transition: background-color 0.3s ease, transform 0.3s ease;
}
/* Button hover effect */
.button1:hover {
background-color: #45a049;
transform: scale(1.05);
}
/* Success message styling */
#successMessage {
font-size: 1.1em;
color: green;
text-align: center;
margin-top: 20px;
}
/* Adjustments for mobile responsiveness */
@media screen and (max-width: 600px) {
input[type="text"], input[type="number"], textarea {
width: 80%;
font-size: 0.95em;
}
.suggestion-title {
font-size: 1.2em;
}
#modifiers {
width: 100%; /* Adjust this percentage to control the width */
}
#abilities {
width: 100%;
}
/* Adjust spacing between different ability modifiers */
#abilities label {
display: block;
margin-bottom: 10px;
line-height: 1.2;
white-space: nowrap;
}
/* Optional: Adjust margin between checkbox and text */
#abilities input[type="checkbox"] {
margin-right: 5px;
}
}
/* Styling for horizontal table */
.weapon-stats-table {
width: 100%;
border-collapse: collapse;
margin: 10px 0;
}
.weapon-stats-table th, .weapon-stats-table td {
border: 1px solid #ddd;
padding: 8px;
text-align: center; /* Centers the text */
}
.weapon-stats-table th {
background-color: #f2f2f2;
color: black;
}
/* Horizontal styling specifically for the table */
.horizontal-table tr:first-child th {
text-align: center;
font-weight: bold;
}
+96
View File
@@ -0,0 +1,96 @@
const cooldownDuration = 10 * 360000;
const prohibitedWords = ['fuck', 'shit', 'asshole', 'bitch', 'bastard', 'damn', 'crap', 'dick', 'piss', 'cunt', 'motherfucker', 'douche',
'prick', 'whore', 'slut', 'fag', 'nigger', 'spic', 'retard', 'twat', 'bollocks', 'wanker', 'bugger', 'arse',
'shithead', 'dumbass', 'jackass', 'dipshit', 'dildo', 'knobhead', 'ballsack', 'buttfucker', 'cum', 'jizz',
'cocksucker', 'fucker', 'skank', 'pussy', 'tits', 'clit', 'schlong', 'dickhead', 'goddamn', 'hell', 'bitchass',
'fuckface', 'shitfaced', 'asshat', 'bint', 'chink', 'gook', 'jap', 'negro', 'dyke', 'queer', 'tranny', 'tosser',
'spaz', 'mong', 'coon', 'beaner', 'cracker', 'wetback', 'homo', 'fudgepacker', 'tard', 'cocks', 'bollocks',
'numbnuts', 'knob', 'muppet', 'git', 'shag', 'minge', 'git', 'bugger', 'tosser', 'nonce', 'plonker', 'pillock']
; // Example word filtering
// Function to get the last submission time from localStorage
function getLastSubmissionTime() {
const storedTime = localStorage.getItem('lastSubmissionTime');
return storedTime ? parseInt(storedTime, 10) : 0;
}
// Function to save the last submission time to localStorage
function setLastSubmissionTime(time) {
localStorage.setItem('lastSubmissionTime', time.toString());
}
function sendMessage() {
// Get the current time
const currentTime = Date.now();
// Retrieve the last submission time from localStorage
const lastSubmissionTime = getLastSubmissionTime();
// Cooldown logic to prevent spamming
if (currentTime - lastSubmissionTime < cooldownDuration) {
alert(`Please wait for ${cooldownDuration / 1000} seconds between submissions.`);
return;
}
// Get the values from the input fields
const pseudoname = document.getElementById("name").value || "Anonymous";
const rating = parseInt(document.getElementById("rate").value, 10);
const comment = document.getElementById("text").value.trim();
// Validation: Rating should be between 1 and 10
if (isNaN(rating) || rating < 1 || rating > 10) {
alert("Rating must be a number between 1 and 10.");
return;
}
// Validation: Comment length (min 5, max 500) and simple prohibited word check
if (comment.length < 5 || comment.length > 500) {
alert("Comment must be between 5 and 500 characters.");
return;
}
// Check for prohibited words (basic check)
for (const word of prohibitedWords) {
if (comment.toLowerCase().includes(word)) {
alert("Your comment contains inappropriate content.");
return;
}
}
// If all checks pass, send the message to the Discord webhook
const request = new XMLHttpRequest();
request.open("POST", "https://discord.com/api/webhooks/1284936894890901649/Zi-2ZV12L1v1OSBoM-DluE1V1LECXilrNNRZYJcxelnwO7rGgXNH47dxvfFEOK7Fe9_J");
request.setRequestHeader('Content-type', 'application/json');
// Create the content to send to the Discord webhook
const content = `**Rating:** ${rating}\n**Comment:**\n${comment}`;
// Debugging information
console.log('Sending message with content:', content);
// Send the message payload to the Discord webhook
const params = {
username: pseudoname, // Pseudoname will appear as the username
content: content // The combined content (pseudoname, rating, and comment)
};
request.send(JSON.stringify(params));
// Update the last submission time to the current time
setLastSubmissionTime(currentTime);
// Optionally, you can reset the form after sending
document.getElementById("name").value = "";
document.getElementById("rate").value = "";
document.getElementById("text").value = "";
// Display the success message
const successMessage = document.getElementById("successMessage");
successMessage.textContent = "Successfully sent the message!";
successMessage.style.display = "block"; // Ensure the message is visible
// Optionally hide the message after a few seconds
setTimeout(() => {
successMessage.style.display = "none"; // Hide message after 3 seconds
}, 3000);
}
+12 -2
View File
@@ -57,7 +57,7 @@
TRL Community with an easy go-to way to calculate DPS and DPM values to help players make informed decisions
about their gameplay. Whether you're fine-tuning your new Deathwish Strategy or simply curious about firearm
performance, we’ve got you covered. If you have suggestions, feedback, or want to contribute new stats or
features, we’d love to hear from you, just contact us on Discord!
features, we’d love to hear from you, just contact us on Discord or on the <a href="{{ url_for('suggestion') }}">Suggestion Page!</a>
</p>
<h2>Our Story</h2>
<p class="about_us_text">
@@ -85,7 +85,17 @@
(damage per second) and DPM (damage per minute) of each weapon via a formula that is also mentioned on Lanz1021' Spreadsheet.</p>
<p class="about_us_text"><b>How often are stats updated?</b></p>
<p class="about_us_text">We update the weapon stats every time a new update is released for TRL.</p><br>
<p class="about_us_text">We update the weapon stats every time a new update is released for TRL.</p>
<h2>Special Thanks</h2>
<p class="about_us_text">
<b>gameknight90999(holdenn/holdenisch)</b>: For telling me what Sandevistan does. (The wiki doesn't tell what it does, lol)<br>
<b>delete(real_delete)</b>: For the info about the 'Weapon Expert' perk (I don't know where else I would've found that).<br>
<b>Epicdragon99999999(epicdog999)</b>: For helping me categorize WW2 and Soviet weapons (I don't think I would've thought about the PKM)<br>
<b>NocturnalAndrea(nocturnalandrea)</b>: For helping me categorize Semi-auto weapons (again, why isn't this listed on the wiki?)<br>
<b>Kris HD(krishd1337)</b>: For the motivation and help with finding bugs.<br>
<b>Lanz1021</b>: For reviewing and giving feedback.<br>
<b>AND YOU!</b>: We are thankful for every visitor we get on this website, and we hope you're enjoying it!
</p>
<h3 class="about_us_text">Thank you for visiting <b>TRL Stats</b>.</h3>
</main>
</body>
+53 -7
View File
@@ -25,6 +25,22 @@
dropdownContent.style.display = "block";
}
}
// Collapsible functionality for perks, buffs, etc.
document.addEventListener('DOMContentLoaded', function () {
var coll = document.getElementsByClassName("collapsible-header");
for (var i = 0; i < coll.length; i++) {
coll[i].addEventListener("click", function () {
this.classList.toggle("active");
var content = this.nextElementSibling;
if (content.style.display === "block") {
content.style.display = "none";
} else {
content.style.display = "block";
}
});
}
});
</script>
</head>
<header>
@@ -53,19 +69,49 @@
</header>
<main>
<label for="weapon-select">Choose a weapon:</label>
<label for="weapon-search"></label>
<input type="text" id="weapon-search" placeholder="Search weapons..." onkeyup="filterWeapons()">
<br>
<label for="weapon-select"></label>
<select id="weapon-select" name="weapons">
<!-- Weapon options will be populated here dynamically -->
<option value="">Select a Weapon</option> <!-- This is the placeholder option -->
</select>
<br>
<div id="guntype-filters">
<label><input type="checkbox" id="primary" value="PRIMARY"> Primary</label>
<label><input type="checkbox" id="secondary" value="SECONDARY"> Secondary</label>
<label><input type="checkbox" id="ww2" value="WW2"> WW2</label>
<label><input type="checkbox" id="soviet" value="SOVIET"> Soviet</label>
<label><input type="checkbox" id="rifle" value="RIFLE"> Rifle</label>
<label><input type="checkbox" id="smg" value="SMG"> SMG</label>
<label><input type="checkbox" id="shotgun" value="SHOTGUN"> Shotgun</label>
<label><input type="checkbox" id="lmg" value="LMG"> LMG</label>
<label><input type="checkbox" id="pistol" value="PISTOL"> Pistol</label>
<label><input type="checkbox" id="special" value="SPECIAL"> Special</label>
<label><input type="checkbox" id="semi-auto" value="SEMI-AUTO"> Semi-Auto</label>
<!-- Add more gun types as needed -->
</div>
<!-- Weapon Stats will be displayed here -->
<label for="operative-search"></label>
<input type="text" id="operative-search" placeholder="Search operatives..." onkeyup="filterOperatives()">
<br>
<label for="operative-select"></label>
<select id="operative-select">
<option value="">Select an operative</option> <!-- This is the placeholder option -->
</select><br>
<!-- Weapon Stats Display -->
<div id="weapon-stats"></div>
<!-- Calculated DPS/DPM results will be shown here -->
<div id="calculated-stats"></div>
<!-- Modifier Checkboxes -->
<div id="modifiers"></div>
<h3>Operative Specific Modifiers</h3>
<div id="operative-modifiers"></div>
<!-- Modifiers Display -->
<div id="modifiers-container">
<div id="modifiers"></div> <!-- Items and Perks go here -->
<div id="abilities"></div> <!-- Abilities go here -->
</div>
<script src="{{ url_for('static', filename='filterWeapons.js') }}"></script>
-2
View File
@@ -55,13 +55,11 @@
<table id="gun-stats" class="background-roster">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Damage</th>
<th>Rounds per minute</th>
<th>Magazine Size</th>
<th>Reload time</th>
<th>Gun type</th>
<th>RPS</th>
<th>DPS</th>
<th>DPM</th>
+4 -27
View File
@@ -63,34 +63,11 @@
<textarea id="text" name="text" rows="4" cols="50" placeholder="Enter your comments here..." minlength="5" maxlength="500" required></textarea><br><br>
</article>
<button class="button1" type="button" onclick="sendMessage()">Send</button>
<!-- Success message (initially hidden) -->
<p id="successMessage" style="display: none; color: green;"></p>
</main>
<script>
function sendMessage() {
const request = new XMLHttpRequest();
request.open("POST", "https://discord.com/api/webhooks/1284936894890901649/Zi-2ZV12L1v1OSBoM-DluE1V1LECXilrNNRZYJcxelnwO7rGgXNH47dxvfFEOK7Fe9_J");
request.setRequestHeader('Content-type', 'application/json');
// Get the values from the input fields
const pseudoname = document.getElementById("name").value || "Anonymous";
const rating = document.getElementById("rate").value;
const comment = document.getElementById("text").value;
// Create the content to send to the Discord webhook
const content = `**Pseudoname:** ${pseudoname}\n**Rating:** ${rating}\n**Comment:**\n${comment}`;
// Debugging information
console.log('Sending message with content:', content);
// Send the message payload to the Discord webhook
const params = {
username: pseudoname, // Pseudoname will appear as the username
content: content // The combined content (pseudoname, rating, and comment)
};
request.send(JSON.stringify(params));
}
</script>
<script src="{{ url_for('static', filename='suggestion.js') }}"></script>
</body>
</html>