Skip to content

Commit a438ec6

Browse files
MrXonteTimGoll
andauthored
C4 Rework (#1739)
Now scales C4 damage with radius and gives consistent damage through walls regardless of line of sight. Relates to #1729 and #1730 although the calculation for proper Killzone is not yet included, but the safe and killzones are now 100% correct. --------- Co-authored-by: Tim Goll <github@timgoll.de>
1 parent 40b7af8 commit a438ec6

File tree

3 files changed

+99
-57
lines changed

3 files changed

+99
-57
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ All notable changes to TTT2 will be documented here. Inspired by [keep a changel
1515
- Added a menu to allow admins to inspect, in detail, how and why roles are distributed as they are (by @nike4613)
1616
- Added option to enable team name next to role name on the HUD (by @milkwxter)
1717
- Added score event for winning with configurable role parameter (by @MrXonte)
18+
- Added ExplosiveSphereDamage game effect for easy calculation of explosion damage through walls (by @MrXonte)
1819

1920
### Fixed
2021

@@ -39,6 +40,7 @@ All notable changes to TTT2 will be documented here. Inspired by [keep a changel
3940
- Fixed a few errors in shop error messages (by @Histalek)
4041
- Fixed `markerVision`'s registry table being able to contain duplicate obsolete entries, thus fixing potential syncing issues with markers (by @TW1STaL1CKY)
4142
- Fixed issue in new Ammo dropping that could cause an error when dropping for modified weapon bases. (by @MrXonte)
43+
- Fixed C4 not showing the correct inflictor when the player is killed (by @TimGoll)
4244

4345
### Changed
4446

@@ -60,6 +62,7 @@ All notable changes to TTT2 will be documented here. Inspired by [keep a changel
6062
- Moved all role-related admin options into the "Roles" menu (by @nike4613)
6163
- Improved description of role layering (by @nike4613)
6264
- Improved the role layering menu by showing which role is enabled and which is disabled (by @TimGoll)
65+
- Reworked C4 damage calculation with new gameEffect ExplosiveSphereDamage (by @MrXonte)
6366

6467
## [v0.14.0b](https://github.com/TTT-2/TTT2/tree/v0.14.0b) (2024-09-20)
6568

gamemodes/terrortown/entities/entities/ttt_c4/shared.lua

Lines changed: 26 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ function ENT:Initialize()
109109
end
110110

111111
if not self:GetRadius() then
112-
self:SetRadius(1000)
112+
self:SetRadius(1500)
113113
end
114114

115115
if not self:GetDmg() then
@@ -145,55 +145,6 @@ function ENT.SafeWiresForTime(t)
145145
end
146146
end
147147

148-
---
149-
-- @param Entity dmgowner
150-
-- @param Vector center
151-
-- @param number radius
152-
-- @realm shared
153-
function ENT:SphereDamage(dmgowner, center, radius)
154-
-- It seems intuitive to use FindInSphere here, but that will find all ents
155-
-- in the radius, whereas there exist only ~16 players. Hence it is more
156-
-- efficient to cycle through all those players and do a Lua-side distance
157-
-- check.
158-
159-
local r = radius * radius -- square so we can compare with dot product directly
160-
161-
-- pre-declare to avoid realloc
162-
local d = 0.0
163-
local diff = nil
164-
local dmg = 0
165-
166-
local plys = playerGetAll()
167-
for i = 1, #plys do
168-
local ply = plys[i]
169-
if ply:Team() ~= TEAM_TERROR then
170-
continue
171-
end
172-
173-
-- dot of the difference with itself is distance squared
174-
diff = center - ply:GetPos()
175-
d = diff:Dot(diff)
176-
177-
if d >= r then
178-
continue
179-
end
180-
181-
-- deadly up to a certain range, then a quick falloff within 100 units
182-
d = math.max(0, math.sqrt(d) - 490)
183-
dmg = -0.01 * (d * d) + 125
184-
185-
local dmginfo = DamageInfo()
186-
dmginfo:SetDamage(dmg)
187-
dmginfo:SetAttacker(dmgowner)
188-
dmginfo:SetInflictor(self)
189-
dmginfo:SetDamageType(DMG_BLAST)
190-
dmginfo:SetDamageForce(center - ply:GetPos())
191-
dmginfo:SetDamagePosition(ply:GetPos())
192-
193-
ply:TakeDamageInfo(dmginfo)
194-
end
195-
end
196-
197148
local c4boom = Sound("c4.explode")
198149

199150
---
@@ -244,11 +195,14 @@ function ENT:Explode(tr)
244195
r_outer = r_outer / 2.5
245196
end
246197

247-
-- damage through walls
248-
self:SphereDamage(dmgowner, pos, r_inner)
249-
250-
-- explosion damage
251-
util.BlastDamage(self, dmgowner, pos, r_outer, self:GetDmg())
198+
gameEffects.ExplosiveSphereDamage(
199+
dmgowner,
200+
ents.Create("weapon_ttt_c4"),
201+
self:GetDmg(),
202+
pos,
203+
r_outer,
204+
r_inner
205+
)
252206

253207
local effect = EffectData()
254208
effect:SetStart(pos)
@@ -903,9 +857,24 @@ else -- CLIENT
903857

904858
local color = COLOR_WHITE
905859

906-
if mvData:GetEntityDistance() > ent:GetRadius() then
860+
--Calculating damage falloff with inverse square method
861+
--100% from 0 to innerRadius
862+
--100% to 0% from innerRadius to outerRadius
863+
--0% from outerRadius to infinity
864+
local dFraction = math.max(
865+
1.0
866+
- math.max(
867+
(mvData:GetEntityDistance() - ent:GetRadiusInner())
868+
/ (ent:GetRadius() - ent:GetRadiusInner()),
869+
0.0
870+
),
871+
0.0
872+
)
873+
local dmg = math.Round(ent:GetDmg() * dFraction * dFraction)
874+
875+
if dmg <= 0 then
907876
mvData:AddDescriptionLine(TryT("c4_marker_vision_safe_zone"), COLOR_GREEN)
908-
elseif mvData:GetEntityDistance() > ent:GetRadiusInner() then
877+
elseif dmg < 100 then
909878
mvData:AddDescriptionLine(TryT("c4_marker_vision_damage_zone"), COLOR_ORANGE)
910879

911880
color = COLOR_ORANGE

lua/ttt2/libraries/game_effects.lua

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,76 @@ function gameEffects.RadiusDamage(dmginfo, pos, radius, inflictor)
148148
end
149149
end
150150

151+
-- Creates explosion damage in a sphere through walls. Very useful for making explosives that aren't line of sight based.
152+
-- @param Player attacker The player that causes this explosion.
153+
-- @param Entity inflictor The entity that causes this explosion.
154+
-- @param number damage The maximum damage done by this explosion.
155+
-- @param Vector origin The center of the explosion.
156+
-- @param number outerRadius The outer border for the explosion damage and its falloff.
157+
-- @param number innerRadius The inner border for the explosion damage where falloff starts.
158+
-- @internal
159+
-- @realm server
160+
function gameEffects.ExplosiveSphereDamage(
161+
attacker,
162+
inflictor,
163+
damage,
164+
origin,
165+
outerRadius,
166+
innerRadius
167+
)
168+
-- It seems intuitive to use FindInSphere here, but that will find all ents
169+
-- in the radius, whereas there exist only ~16 players. Hence it is more
170+
-- efficient to cycle through all those players and do a Lua-side distance
171+
-- check.
172+
173+
if outerRadius < innerRadius then
174+
ErrorNoHalt(
175+
"[Game Effects Explosive Sphere Damage] Outer radius too high! Setting both radi to outer radius."
176+
)
177+
innerRadius = outerRadius
178+
end
179+
180+
-- pre-declare to avoid realloc
181+
local d = 0.0
182+
local dFraction = 0.0
183+
local diff = nil
184+
local dmg = 0
185+
local radiDiff = (outerRadius - innerRadius)
186+
local plys = player.GetAll()
187+
for i = 1, #plys do
188+
local ply = plys[i]
189+
190+
if not IsValid(ply) or not ply:IsTerror() then
191+
continue
192+
end
193+
194+
diff = origin - (ply:GetPos() + ply:OBBCenter())
195+
--we are using Length on purpose here. We would need a sqrt somewhere anyway and with this we dont need to square the radi
196+
d = diff:Length()
197+
--we now turn this into a % of damage based of the value of d
198+
--100% from 0 to innerRadius
199+
--100% to 0% from innerRadius to outerRadius
200+
--<0% from outerRadius to infinity
201+
dFraction = 1.0 - math.max((d - innerRadius) / radiDiff, 0.0)
202+
203+
--Next Iteration if we are outside the radius
204+
if dFraction < 0.0 then
205+
continue
206+
end
207+
208+
dmg = math.Round(damage * dFraction * dFraction)
209+
210+
local dmginfo = DamageInfo()
211+
dmginfo:SetDamage(dmg)
212+
dmginfo:SetAttacker(attacker)
213+
dmginfo:SetInflictor(inflictor)
214+
dmginfo:SetDamageType(DMG_BLAST)
215+
dmginfo:SetDamageForce(diff)
216+
dmginfo:SetDamagePosition(ply:GetPos() + ply:OBBCenter())
217+
ply:TakeDamageInfo(dmginfo)
218+
end
219+
end
220+
151221
-- vFIRE INTEGRATION
152222

153223
if SERVER then

0 commit comments

Comments
 (0)