Skip to content

Commit

Permalink
happens to the best of us
Browse files Browse the repository at this point in the history
  • Loading branch information
uniboi committed Dec 30, 2022
1 parent ac39e54 commit 8e13d6e
Show file tree
Hide file tree
Showing 4 changed files with 314 additions and 42 deletions.
27 changes: 1 addition & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1 @@
# NSModTemplate
A template repository for Northstar mods with a ~~mostly~~ pre-configured github action for publishing to Thunderstore

## Usage
<ol>
<li> Click the <code>Use this template</code> button on the top right of the repo's landing page (<a href="https://github.com/GreenTF/NSModTemplate">here</a>)</li>
<li> Give the new repo a name and make sure it's set to <code>public</code></li>
<li> <details><summary> In the <code>settings</code> tab, under <code>actions</code> -> <code>general</code>, set <code>Actions permissions</code> to <code>Allow all actions and reusable workflows</code></summary>
<img src="https://user-images.githubusercontent.com/4367791/180306016-04bfc321-b60f-4ed0-ac0c-5a6065036e2c.png" />
</details></li>
<li> <details><summary> Also in <code>settings</code>, under <code>secrets</code> -> <code>actions</code>, add your Thunderstore token as a secret named <code>TS_KEY</code> (Steps for getting a token can be found <a href="https://github.com/GreenTF/upload-thunderstore-package/wiki">here</a>)</summary>
<img src="https://user-images.githubusercontent.com/4367791/180306285-60dd51ec-0448-44af-aa92-682599c6c0f4.png" />
<img src="https://user-images.githubusercontent.com/4367791/180306391-a217f309-e875-4e74-8270-8155c60dbcdc.png" />
</details>
</li>
<li> <details><summary>Edit <code>.github/workflows/publish.yml</code> ~line 43 to add a description for your mod </summary>
<img src="https://user-images.githubusercontent.com/4367791/180337843-5213db45-850b-4759-98c5-9ad47cbab7ba.png" />
</details>
</li>

<li> Update this README and <code>icon.png</code> as they will be used by Thunderstore as well </li>
<li> Write your mod! (HINT: Find the docs <a href="https://r2northstar.readthedocs.io/en/latest/guides/gettingstarted.html">here</a>) </li>
<li> Before pushing large files (100mb or larger), run <code>concat_assets.sh</code> and commit the archives instead. Your archives will be automatically concatted and extracted when creating a github release so the mod is downloadable from thunderstore without any extra steps</li>
</ol>


#idk
40 changes: 24 additions & 16 deletions mod.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
{
"Name": "Example.Mod",
"Description": "A cool mod that does cool stuff",
"Version": "1.0.0",
"DownloadLink": "https://northstar.thunderstore.io/package/download/Example/Mod/",

"LoadPriority": 0,
"ConVars": [],
"Scripts": [{
"Path": "example.nut",
"RunOn": "(CLIENT || SERVER) && MP"
"ClientCallback": {
"Before":"example_callback"
}
}],
"Localisation": []
}
"Name": "Odd.Holosprays",
"Description": "A cool mod that does cool stuff",
"Version": "1.0.0",
"DownloadLink": "https://northstar.thunderstore.io/package/download/Example/Mod/",
"LoadPriority": 0,
"ConVars": [],
"Scripts": [
{
"Path": "holosprays.nut",
"RunOn": "SERVER",
"ServerCallback": {
"Before": "InitHoloSpray"
}
},
{
"Path": "playerPings.nut",
"RunOn": "SERVER",
"ServerCallback": {
"Before": "InitPlayerPings"
}
}
],
"Localisation": []
}
175 changes: 175 additions & 0 deletions mod/scripts/vscripts/holoSprays.nut
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
global function InitHoloSpray
global function CreateSprite
global function TraceFromEnt
struct SprayInfo {
asset material
float scale
string color
vector offset // extra position offset from the base
}

SprayInfo function _SprayInfo( asset material, float scale = 0.75, string color = "200 200 200", vector offset = <0,0,30> )
{
PrecacheSprite( material )
SprayInfo s
s.material = material
s.scale = scale
s.color = color
s.offset = offset
return s
}


table< entity, array<entity> > holoSpraysOfPlayer
array<SprayInfo> sprayInfos

void function InitHoloSpray()
{
sprayInfos = [
_SprayInfo( $"materials/ui/scoreboard_mcorp_logo.vmt", 0.5, "200 200 200", <0,0,60> )
_SprayInfo( $"materials/ui/scoreboard_imc_logo.vmt", 0.5, "200 200 200", <0,0,60> )
]
AddCallback_OnClientConnected(OnPlayerConnected)
AddCallback_OnClientDisconnected(OnPlayerDisconnected)
}

void function OnPlayerConnected( entity player )
{
AddButtonPressedPlayerInputCallback( player, IN_USE, OnUseHoloSpray )
holoSpraysOfPlayer[player] <- []
thread void function() : ( player ) {
wait RandomFloatRange( 0.0, 0.5 )
NSSendInfoMessageToPlayer( player, "You can use HOLOSPRAYS on this server, simply press %%use%% to throw yours" )
}()

}

void function OnPlayerDisconnected( entity player )
{
foreach( entity spray in holoSpraysOfPlayer[ player ] )
{
if( !IsValid( spray ) )
continue
spray.Destroy()
}
delete holoSpraysOfPlayer[ player ]
}


void function OnUseHoloSpray( entity player )
{
array<entity> sprays = holoSpraysOfPlayer[ player ]
if(sprays.len() >= 5) //spam is not cool
{
sprays[0].Destroy() // destroy the base
holoSpraysOfPlayer[player] = sprays.slice(1) // remove the reference
}

const float force = 500.0 // initial force of the base pad
entity base = CreatePropPhysics( $"models/gameplay/health_pickup_small.mdl", player.EyePosition() - <0,0,20>, <0,0,0> )
base.kv.solid = 0

base.SetOwner( player )

thread SpawnHoloSprite( base )

holoSpraysOfPlayer[player].append( base )
base.SetVelocity( ( player.GetViewVector() ) * force )
}

void function SpawnHoloSprite( entity base )
{
base.EndSignal( "OnDestroy" )
entity sprite
entity light
WaitFrame()

while( IsValid( base ) )
{

TraceResults hit = OriginToFirst( base )
if( Length( base.GetOrigin() - hit.endPos ) <= 10 ) //is object close to the floor
{
//make sure the object doesnt roll
base.SetVelocity( <0,0,0> )
//adjust angles to surface, <-90,0,0> is needed because we went the medkit to lie down flat
base.SetAngles( < -90,0,0 > + AnglesOnSurface( hit.surfaceNormal, AnglesToForward( base.GetAngles() ) ) )

entity mover = CreateExpensiveScriptMover( base.GetOrigin(), base.GetAngles() )
base.SetParent( mover )
mover.NonPhysicsMoveTo( hit.endPos + <0,0,5.5>, 0.3, 0.0, 0.0 )

base.SetParent( hit.hitEnt )

//make sure the object doesnt rotate too much
base.StopPhysics()

SprayInfo info = sprayInfos.getrandom()
sprite = CreateSprite( base.GetCenter() + info.offset, <0,0,0>, info.material, "200 200 200", info.scale )
sprite.SetParent( base )
light = CreateSprite( base.GetCenter() + <0,0,6.5>, <0,0,0>, $"sprites/glow_05.vmt", "200 200 200", 0.75 )
light.SetParent( base )

break
}
WaitFrame()
}
}

// Trace straight down from the provided origin until the trace hits the world, a mover or a Titan (Titans break idk)
TraceResults function OriginToFirst( entity base )
{
entity lastHit
TraceResults traceResult
array<entity> ignore = []
vector origin1 = base.GetOrigin()
vector origin = origin1 + <1,1,1>
printt( "TEST " , origin)
printt( "TEST2 " , <origin.x, origin.y, origin.z - 2000> )
printt( "BASE ", base)
printt( "OWNER ", base.GetOwner() )
printt( "NAME ", base.GetOwner().GetPlayerName() )

do
{
vector endOrigin = <origin.x, origin.y, origin.z - 2000>
traceResult = TraceLine( origin, endOrigin, ignore, TRACE_MASK_NPCWORLDSTATIC, TRACE_COLLISION_GROUP_NONE )
lastHit = traceResult.hitEnt
if(!IsValid(lastHit))
continue
ignore.append( traceResult.hitEnt )
} while( IsValid( lastHit ) && !lastHit.IsWorld() && !lastHit.IsTitan() && !(lastHit.GetClassName() == "worldspawn") && !(lastHit instanceof CNPC_Titan) && !(lastHit.GetClassName() == "script_mover") )
return traceResult
}

// Create a 2D sprite at position
entity function CreateSprite( vector origin, vector angles, asset sprite, string lightcolor = "255 0 0", float scale = 0.5, int rendermode = 9 )
{
// attach a light so we can see it
entity env_sprite = CreateEntity( "env_sprite" )
env_sprite.SetScriptName( UniqueString( "molotov_sprite" ) )
env_sprite.kv.rendermode = rendermode //these do NOT follow any pattern, trial an error is your friend, as you dont have any others anyway (they go from like 1 to 10 or sth, I hontely dont know)
env_sprite.kv.origin = origin
env_sprite.kv.angles = angles
env_sprite.kv.rendercolor = lightcolor
env_sprite.kv.renderamt = 255
env_sprite.kv.framerate = "10.0"
env_sprite.SetValueForModelKey( sprite )
env_sprite.kv.scale = string( scale )
env_sprite.kv.spawnflags = 1
env_sprite.kv.GlowProxySize = 16.0
env_sprite.kv.HDRColorScale = 1.0
DispatchSpawn( env_sprite )
EntFireByHandle( env_sprite, "ShowSprite", "", 0, null, null )

return env_sprite
}

// Trace to the point an entity looks at
TraceResults function TraceFromEnt( entity p )
{
TraceResults traceResults = TraceLineHighDetail( p.EyePosition(),
p.EyePosition() + p.GetViewVector() * 10000,
p, TRACE_MASK_SHOT, TRACE_COLLISION_GROUP_NONE )
return traceResults
}
114 changes: 114 additions & 0 deletions mod/scripts/vscripts/playerPings.nut
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
global function InitPlayerPings

struct Ping {
entity sprite
float time
}

table< entity, array<Ping> > playerPings
const PING_DURATION = 15.0

void function InitPlayerPings()
{
PrecacheSprite($"materials/ui/hud/attacker_offscreen.vmt")
PrecacheSprite($"materials/vgui/hud/weapons/target_ring_arc_tool_inner.vmt")
RegisterSignal( "PingDestroyed" )

AddCallback_OnClientConnected(OnPlayerConnected)
AddCallback_OnClientDisconnected(OnPlayerDisconnected)
}

void function OnPlayerConnected( entity player )
{
AddButtonPressedPlayerInputCallback( player, IN_PING, OnUsePing )
playerPings[ player ] <- []
}

void function OnPlayerDisconnected( entity player )
{
//avoid a crash by removing their pings
delete playerPings[player]
}

string function GenerateRGBValueByIndex( int index )
{
//if somehow the player was not found in the array of his team it doesnt crash
if( index == -1 )
return "100 100 100"

int[3] RGBValue

//rotates the columns around for each index
int changeRGBindex = index % 3

int potentialNewColour = RGBValue[ changeRGBindex ] + index * 50
RGBValue[ changeRGBindex ] = potentialNewColour > 255 ? potentialNewColour % 255 : potentialNewColour

//following column of the first one LOL
changeRGBindex = (index+1) % 3
RGBValue[ changeRGBindex ] = 200 // fix value for RGB that constantly roates infront of the changine value

return format( "%i %i %i", RGBValue[0], RGBValue[1], RGBValue[2] )
}


void function OnUsePing( entity player )
{
thread SpawnPing( player )
}

bool function isEnemyPing( entity player, vector newPing )
{
foreach( Ping p in playerPings[ player ] )
{
if( Time() - p.time <= 1.0 && LengthSqr( p.sprite.GetOrigin() - newPing ) <= 2000.0 )
{
Signal( p, "PingDestroyed" )
p.sprite.Destroy()
playerPings[ player ].fastremovebyvalue( p )
return true
}
}
return false
}

void function SpawnPing( entity player )
{
//all pings for a player so far
array<Ping> pings = playerPings[player]
if(pings.len() >= 5) //spam is not cool
{
Signal( pings[0], "PingDestroyed" )
if( IsValid( pings[0].sprite ) )
pings[0].sprite.Destroy()
playerPings[player] = pings.slice(1)
}

TraceResults trace = TraceFromEnt( player )
bool enemyPing = isEnemyPing( player, trace.endPos )
entity sprite = CreateSprite( trace.endPos, <0,0,0>, enemyPing ? $"materials/ui/hud/attacker_offscreen.vmt" : $"materials/vgui/hud/weapons/target_ring_arc_tool_inner.vmt", enemyPing ? "255 0 0" : GenerateRGBValueByIndex( GetPlayerArrayOfTeam( player.GetTeam( ) ).find(player) ), enemyPing ? 0.6 :0.3 , 5 ) // 5
SetTeam( sprite, player.GetTeam() )
//set it so only you can your team can see them
sprite.kv.VisibilityFlags = ENTITY_VISIBLE_TO_FRIENDLY | ENTITY_VISIBLE_TO_OWNER
//
sprite.SetOwner( player )
//makes the ping attach to the object that moves
sprite.SetParent( trace.hitEnt )
//track the time a ping was send
Ping p
p.sprite = sprite
p.time = Time()
playerPings[player].append( p )

//ping gets detroyed after a set time
thread DestroyPingDelayed( p, PING_DURATION )
}

void function DestroyPingDelayed( Ping p, float duration )
{
EndSignal( p, "PingDestroyed" )
wait duration
if( IsValid( p.sprite ) )
p.sprite.Destroy()
playerPings[ p.sprite.GetOwner() ].slice( 1 )
}

0 comments on commit 8e13d6e

Please sign in to comment.