Skip to content

Throwing weapons #31

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
49 changes: 49 additions & 0 deletions Content/Entities/Tools/FastThrow.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@

namespace TC2.Base.Components
{
public static partial class FastThrow
{
[IComponent.Data(Net.SendType.Reliable, name: "Throwing Speed")]
public partial struct Data: IComponent
{
[Statistics.Info("Throwing Speed", description: "Additional speed added to this object when thrown", format: "{0:0.##}", comparison: Statistics.Comparison.Higher, priority: Statistics.Priority.High)]
public float added_speed = 10.00f;

[Save.Ignore, Net.Ignore] public bool last_attach = false;

public Data()
{

}
}

[ISystem.EarlyUpdate(ISystem.Mode.Single)]
public static void OnUpdate(ISystem.Info info, Entity entity, [Source.Owned] ref FastThrow.Data throwing, [Source.Owned] ref Body.Data body,
[Source.Owned] in Transform.Data transform)
{

#if SERVER

var ent_holder = entity.GetParent(Relation.Type.Child);

if (ent_holder.IsAlive())
{
if(throwing.last_attach != true)
{
//App.WriteLine("attach");
throwing.last_attach = true;
}
}
else if(throwing.last_attach)
{
//App.WriteLine("speed");
var dir = body.GetVelocity();
dir = dir.GetNormalized();
body.AddForce(dir * Maths.Min(body.GetMass(), 20.0f) * throwing.added_speed * App.tickrate);
throwing.last_attach = false;
body.Sync<Body.Data>(entity);
}
#endif
}
}
}
147 changes: 147 additions & 0 deletions Content/Entities/Tools/ThrowingDamage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@

namespace TC2.Base.Components
{
public static partial class ThrowingDamage
{
[IComponent.Data(Net.SendType.Reliable, name: "Throwing Damage")]
public partial struct Data: IComponent
{
[Statistics.Info("Added Damage", description: "Added damage when throwing the object, multiplied by velocity.", format: "{0:0}", comparison: Statistics.Comparison.Higher, priority: Statistics.Priority.High)]
public float damage = default;

[Statistics.Info("Base Damage Type", description: "Type of damage dealt.", format: "{0}", comparison: Statistics.Comparison.None, priority: Statistics.Priority.Low)]
public Damage.Type damage_type = Damage.Type.Blunt;

[Statistics.Info("Includes Melee", description: "Whether or not throwing damage includes any pre existing melee damage and damage type.", format: "{0}", comparison: Statistics.Comparison.None, priority: Statistics.Priority.Low)]
public bool overrideWithMelee = true;

[Save.Ignore, Net.Ignore] public float next_hit = default;
[Save.Ignore, Net.Ignore] public float last_attach = default;

public bool collision = false;

public Data()
{

}
}

[ISystem.EarlyUpdate(ISystem.Mode.Single)]
public static void OnUpdate(ISystem.Info info, Entity entity, [Source.Owned] ref ThrowingDamage.Data throwing, [Source.Owned] ref Body.Data body,
[Source.Owned] in Transform.Data transform)
{
var ts = Timestamp.Now();

#if SERVER
var hit = false;
var can_hit = info.WorldTime >= throwing.next_hit;

var ent_holder = entity.GetParent(Relation.Type.Child);

if (ent_holder.IsAlive())
{
//App.WriteLine("attach");
throwing.last_attach = info.WorldTime;
throwing.collision = false;
}
else
{
var time = info.WorldTime - throwing.last_attach;
if(time < 0.20f)
{

}
else if (time < 0.25f)
{
//App.WriteLine("drop");
throwing.collision = true;
}
else if(throwing.collision)
{
var damagetype = throwing.damage_type;
var basedamage = throwing.damage * 0.1f;

ref var melee = ref entity.GetComponent<Melee.Data>(); //Copies melee damage type if the item has one
if(!melee.IsNull() && throwing.overrideWithMelee)
{
damagetype = melee.damage_type;
var random = XorRandom.New();
basedamage = basedamage + melee.damage_base * 0.1f + random.NextFloatRange(0.00f, melee.damage_bonus) * 0.1f;
//This is multiplied by velocity so the 0.1 multiplier mitigates this and encourages high speed throwing attacks

}

foreach (var arbiter in body.GetArbiters())
{
var ent_hit = arbiter.GetEntity();

if (can_hit)
{
var material_type = arbiter.GetMaterial();
var vel = arbiter.GetVelocity() - body.GetVelocity();
var vel_sq = vel.Length();
hit = true;
//App.WriteLine("speed" + vel + " " + vel_sq);
if (ent_hit.IsValid() && vel_sq > 1.00f)
{
entity.Hit(ent_hit, ent_hit, arbiter.GetPosition(), -arbiter.GetNormal(), arbiter.GetNormal(),
damage: basedamage * vel_sq, target_material_type: material_type, damage_type: damagetype);
}
}
}
}
}

if (hit)
{
//App.WriteLine("stop");
throwing.next_hit = info.WorldTime + 0.40f;
throwing.collision = false;
}
#endif
}


[ISystem.LateUpdate(ISystem.Mode.Single)]
public static void OnLateUpdateLine(ISystem.Info info, Entity entity, [Source.Owned] ref ThrowingDamage.Data throwing, [Source.Owned] ref Body.Data body,
[Source.Owned, Pair.Of<Body.Data>] ref Shape.Line shape)
{
bool mask = shape.mask.HasFlag(Physics.Layer.Solid);
if(throwing.collision != mask)
{
shape.mask.SetFlag(Physics.Layer.Creature, throwing.collision);
shape.mask.SetFlag(Physics.Layer.Solid, throwing.collision);
body.Rebuild();
//shape.Sync<Shape.Line, Body.Data>(entity);
}
}

[ISystem.LateUpdate(ISystem.Mode.Single)]
public static void OnLateUpdateBox(ISystem.Info info, Entity entity, [Source.Owned] ref ThrowingDamage.Data throwing, [Source.Owned] ref Body.Data body,
[Source.Owned, Pair.Of<Body.Data>] ref Shape.Box shape)
{
bool mask = shape.mask.HasFlag(Physics.Layer.Solid);
if(throwing.collision != mask)
{
shape.mask.SetFlag(Physics.Layer.Creature, throwing.collision);
shape.mask.SetFlag(Physics.Layer.Solid, throwing.collision);
body.Rebuild();
//shape.Sync<Shape.Box, Body.Data>(entity);
}
}

[ISystem.LateUpdate(ISystem.Mode.Single)]
public static void OnLateUpdateCircle(ISystem.Info info, Entity entity, [Source.Owned] ref ThrowingDamage.Data throwing, [Source.Owned] ref Body.Data body,
[Source.Owned, Pair.Of<Body.Data>] ref Shape.Circle shape)
{
bool mask = shape.mask.HasFlag(Physics.Layer.Solid);
if(throwing.collision != mask)
{
shape.mask.SetFlag(Physics.Layer.Creature, throwing.collision);
shape.mask.SetFlag(Physics.Layer.Solid, throwing.collision);
body.Rebuild();
//shape.Sync<Shape.Circle, Body.Data>(entity);
}
}
}
}
128 changes: 128 additions & 0 deletions content/Augments/Augments.cs
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,134 @@ private static void RegisterAugments(ref List<Augment.Definition> definitions)
// }
//));

definitions.Add(Augment.Definition.New<Holdable.Data>
(
identifier: "holdable.aggressive_throw",
category: "Utility",
name: "Agressive Throw",
description: "When throw the object now deals damage and collides with things.",

can_add: static (ref Augment.Context context, in Holdable.Data data, ref Augment.Handle handle, Span<Augment.Handle> augments) =>
{
return !context.HasComponent<ThrowingDamage.Data>();
},

apply_0: static (ref Augment.Context context, ref Holdable.Data data, ref Augment.Handle handle, Span<Augment.Handle> augments) =>
{
ref var throwingdamage = ref context.GetOrAddComponent<ThrowingDamage.Data>();
throwingdamage.damage = 200.00f;
throwingdamage.damage_type = Damage.Type.Blunt;
},

apply_1: static (ref Augment.Context context, ref Holdable.Data data, ref Augment.Handle handle, Span<Augment.Handle> augments) =>
{
foreach (ref var requirement in context.requirements_new)
{
if (requirement.type == Crafting.Requirement.Type.Work)
{
requirement.amount *= 1.20f;
}
}
}
));

definitions.Add(Augment.Definition.New<Holdable.Data>
(
identifier: "holdable.throwing_leverage",
category: "Utility",
name: "Throwing Leverage",
description: "When thrown object now travels faster and further.",

can_add: static (ref Augment.Context context, in Holdable.Data data, ref Augment.Handle handle, Span<Augment.Handle> augments) =>
{
return !context.HasComponent<FastThrow.Data>();
},

apply_0: static (ref Augment.Context context, ref Holdable.Data data, ref Augment.Handle handle, Span<Augment.Handle> augments) =>
{
ref var fastthrow = ref context.GetOrAddComponent<FastThrow.Data>();
fastthrow.added_speed = 10.00f;
},

apply_1: static (ref Augment.Context context, ref Holdable.Data data, ref Augment.Handle handle, Span<Augment.Handle> augments) =>
{
foreach (ref var requirement in context.requirements_new)
{
if (requirement.type == Crafting.Requirement.Type.Work)
{
requirement.amount *= 1.40f;
requirement.difficulty += 2.00f;
}
}
}
));

definitions.Add(Augment.Definition.New<FastThrow.Data>
(
identifier: "fastThrow.motion_acceleration",
category: "Utility",
name: "Accelerated Throw",
description: "When thrown object now travels faster using motion.",

can_add: static (ref Augment.Context context, in FastThrow.Data data, ref Augment.Handle handle, Span<Augment.Handle> augments) =>
{
return !augments.HasAugment(handle);
},

apply_0: static (ref Augment.Context context, ref FastThrow.Data data, ref Augment.Handle handle, Span<Augment.Handle> augments) =>
{
ref var fastthrow = ref context.GetOrAddComponent<FastThrow.Data>();
fastthrow.added_speed += 10.00f;
},

apply_1: static (ref Augment.Context context, ref FastThrow.Data data, ref Augment.Handle handle, Span<Augment.Handle> augments) =>
{
foreach (ref var requirement in context.requirements_new)
{
if (requirement.type == Crafting.Requirement.Type.Work)
{
requirement.difficulty += 2.00f;
}
}
context.requirements_new.Add(Crafting.Requirement.Resource("pellet.motion", 1.00f));
}
));

definitions.Add(Augment.Definition.New<ThrowingDamage.Data>
(
identifier: "throwingDamage.added_spikes",
category: "Utility",
name: "Added Spikes",
description: "When thrown the object now deals more damage and stabs.",

can_add: static (ref Augment.Context context, in ThrowingDamage.Data data, ref Augment.Handle handle, Span<Augment.Handle> augments) =>
{
return !augments.HasAugment(handle);
},

apply_0: static (ref Augment.Context context, ref ThrowingDamage.Data data, ref Augment.Handle handle, Span<Augment.Handle> augments) =>
{
ref var throwingdamage = ref context.GetOrAddComponent<ThrowingDamage.Data>();
throwingdamage.damage += 200.00f;
throwingdamage.damage_type = Damage.Type.Stab;
},

apply_1: static (ref Augment.Context context, ref ThrowingDamage.Data data, ref Augment.Handle handle, Span<Augment.Handle> augments) =>
{
foreach (ref var requirement in context.requirements_new)
{
if (requirement.type == Crafting.Requirement.Type.Resource)
{
requirement.amount *= 1.30f;
}
else if (requirement.type == Crafting.Requirement.Type.Work)
{
requirement.amount *= 1.10f;
}
}
}
));

definitions.Add(Augment.Definition.New<Telescope.Data>
(
identifier: "telescope.long_focus_lens",
Expand Down
5 changes: 5 additions & 0 deletions content/Entities/Tools/Axe/prefab.axe.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ melee.state:

}

throwingDamage:
{

}

aimable:
{

Expand Down
5 changes: 5 additions & 0 deletions content/Entities/Tools/Club/prefab.Club.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ melee.state:

}

throwingDamage:
{

}

aimable:
{

Expand Down
5 changes: 5 additions & 0 deletions content/Entities/Tools/Crowbar/prefab.Crowbar.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ melee.state:

}

throwingDamage:
{

}

aimable:
{

Expand Down
10 changes: 10 additions & 0 deletions content/Entities/Tools/Knife/prefab.Knife.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,21 @@ melee.state:

}

throwingDamage:
{

}

aimable:
{

}

fastThrow:
{
addedspeed: 8.00
}

holdable:
{
offset: [-0.500, 0.000]
Expand Down
Loading