I was recently struck by the idea that everything in the universe is bound by gravity on a grand (Planets, stars) and minute (Atoms, molecules) scale, so I figured I'd do a little test on simulating gravity in Gmod.
I started off with a bunch of randomly-generated planets and a "sun" which dragged the planets towards it gradually (killing any that got too close), however I noticed that this didn't produce anything like the orbits we see in normal solar systems. However, I did discover by accident when I shifted the origin point of the sun (The E2 chip) that the planets spontaneously acquired a regular circular orbit.
So my next attempt was focused more on roaming particles, with each every element moving and pulling on and being pulled by every other element. How strongly each element was pulled depended of course on the density of the other element. So denser elements could very easily draw in less-dense elements, or very gradually pull together with other dense elements. ("Elements" here refers purely to a simulated object, not actual periodic elements of stars or such)
The way gravity works in this simulator is by directional velocity. Each element starts with an initial velocity, and then each other element pulls the element towards itself by an amount determined based on the element's density and distance by adding the subsequent vector to the element's velocity. As the simulator runs, the elements each move according to their new velocities, causing their directional pulls and positions to change, resulting in some rather surprising displays.
In this simple simulator, I've seen systems occur that resembled binary star systems, that look like ordinary one-star solar systems (As little elements whizz around a dense element), and even different elements pulling together to form a stronger collective gravity well, potentially forming heavier (periodic) elements or stars and black holes, depending on how you interpret the simulation.
And now, the code:
@name Gravity simulator
@persist Units U Base:vector RV
@persist Gr G State Slimit Dist
if(first()){
gSetGroup("atoms")
gDeleteAll()
U=1
Units=10 #Number of units to simulate
Slimit=75 #Speed limit of all units
Base=entity():pos() #Starting point for generation
Dist=1 #Gravity weaken over distance?
RV=1 #Randomised initial velocity
#If disabled, begins travelling from base point
}
if(U<=Units){interval(1000)}
else{runOnTick(1)}
M=0
#Unit generation
while(U<=Units & M<=10){
#Initial position
Vec=randvec()*random(0,1000)
Vec+=Base
#Initial Velocity
if(RV){
Vel=randvec()*random(0,Slimit)
}
else{
Vel=(Base-Vec):normalized()*min(Slimit,Vec:length())
}
gSetVec(U,Vel)
#Density
Den=round(random(0,255))
holoCreate(U,Vec,vec(1,1,1)*2)
holoModel(U,"hqicosphere2")
holoColor(U,vec(1,1,1)*Den)
holoAng(U,Vel:toAngle())
holoEntity(U):setTrails(5,5,10,"trails/plasma",vec(0,1,1)*255,255)
M++,U++
}
#Gravity function
if(tickClk()){
Une=holoEntity(Gr)
Vel=gGetVec(Gr)
Mass=Une:getColor():x()
Vec=Une:pos()
while(G<=Units & M<=30){
Ent=holoEntity(G)
if(G!=Gr & Ent){
Pos=Ent:pos()
Dis=Vec:distance(Pos)
#Gravity elements
Den=Ent:getAlpha() #Density
Rel=(Une:pos()-Pos):normalized() #Relative direction
Vel-=(Rel*(Den/Mass))*(Dist ? (1-min(Dis/700,1)) : 1)
gSetVec(Gr,Vel:normalized()*min(Vel:length(),Slimit))
#Heat
if(Dis<=100){
D=1-(Dis/100)
Hot=vec(1,1,0)*D
#holoColor(Gr,Une:getColor()+Hot)
}
}
M++,G++
}
if(G>=Units){
NP=Une:pos()+Vel
holoPos(Gr,NP)
holoAng(Gr,Vel:toAngle())
Gr=(Gr>=Units ? 1 : Gr+1)
G=0
}
}
Thursday, 28 January 2010
Tuesday, 26 January 2010
The Gbrain - Data storage
There's many ways to store information in Wiremod, chief among them being tables & arrays in expression 2. The Gbrain neurons however have a serious memory issue.
The rule of thumb is that the fewers variables a given neuron looks at, the less combinations there can be, and therefore the less information it needs to store. However, even then, with any significant complexity, the neurons start running into tables the size of Big Ben (That's the big London clocktower, by the by, not Ben the morbidly obese guy on the subway).
Therefore, we need to consider ways to store and manage the data.
One possibility is to store each sequence of relevant variables and then have a glon-encoded table for each encountered action. An action that has not been encountered begins with a modifier of zero, of course, so it is irrelevant at that point as it should be, and then amended following consequence evaluation. This does little to reduce the memory footprint, but it does mean we don't need a whole new entry each time a different action is undertaken with previously-encountered circumstance.
Another is to have a super-array, containing an ordered sequence of glon-encoded tables which are unpacked and checked for the relevant entry. This means the memory footprint is a fraction of the overall data, and the neuron can be easily coded to loop through the different tables until it finds the right entry (if any) and to make a new table once the most recent one reaches a critical entry mass, storing it in the next entry of the super-array. The downside however is that, as the number of stored tables increases, so does the time it takes the neuron to search for the entry, whether or not the neuron has actually encountered the circumstance.
This latter option is probably what I'll be using for Gbrain, probably hybridised with the former to reduce the footprint further. The amount of time it spends looking in a table that lacks the circumstance is so minimal it could almost be said to never have happened.
Management of the data predominantly refers to how you search through it to find what you need, but since I've covered that above I'll more right to cutting down repeats and such. Good coding means you'll never have the same entry twice, so cutting down instead refers here to removing entries that are no-longer relevant or needed. Management of the database is necessary because of some easy math we can do right now.
Let's say we start off wholesale with 10,000 entries, determining the different actions and circumstances associated. Next, let's assume for each circumstance we've considered each action at least once, and that there are 5 actions (Left, right, forward, back, turn etc.). Then, in our stage 2 circumstance tables, let's assume we have about 50 entries each. Therefore overall we have (10000/5)/50 entries in the super-array. That's 40 entries, not much until you consider that for all the irrelevant or otherwise meaningless entries we still have to sort through all 40 of them when looking for previous data, that means each entry is more time it takes for an action to be considered or added. Culling the herd makes the gBrain faster and less memory heavy.
This is a tricky thing, because you're essentially programming "forgetfulness" into your system, which is an odd idea at the best of times. The best way I can think of is to include a reference array of the entries and when they were last modified. Then, every so often, run through the reference array checking the oldest entries. Obviously if we flat-out erased the oldest data, we could "forget" not to stick our hands in an open flame or to take a blind leap off a cliff.
Instead, before outright deleting something, instead first consider it's modifier. A strong modifier either way (Yes/No) should mean that this is something the brain has encountered often enough to decide firmly what to do in that situation, meaning something it definitively needs to do or avoid doing. This is an entry we don't want to lose, because we would then risk future operation safety.
Therefore instead delete entries with modifiers closer to zero on both counts, these are ones we've either encountered little or that are reasonably neutral on going either way anyway. Remember: Creating a new entry is resource-free, as is not finding an entry in the database. And the smaller the database is kept, the faster the neuron can decide what to do.
The rule of thumb is that the fewers variables a given neuron looks at, the less combinations there can be, and therefore the less information it needs to store. However, even then, with any significant complexity, the neurons start running into tables the size of Big Ben (That's the big London clocktower, by the by, not Ben the morbidly obese guy on the subway).
Therefore, we need to consider ways to store and manage the data.
One possibility is to store each sequence of relevant variables and then have a glon-encoded table for each encountered action. An action that has not been encountered begins with a modifier of zero, of course, so it is irrelevant at that point as it should be, and then amended following consequence evaluation. This does little to reduce the memory footprint, but it does mean we don't need a whole new entry each time a different action is undertaken with previously-encountered circumstance.
Another is to have a super-array, containing an ordered sequence of glon-encoded tables which are unpacked and checked for the relevant entry. This means the memory footprint is a fraction of the overall data, and the neuron can be easily coded to loop through the different tables until it finds the right entry (if any) and to make a new table once the most recent one reaches a critical entry mass, storing it in the next entry of the super-array. The downside however is that, as the number of stored tables increases, so does the time it takes the neuron to search for the entry, whether or not the neuron has actually encountered the circumstance.
This latter option is probably what I'll be using for Gbrain, probably hybridised with the former to reduce the footprint further. The amount of time it spends looking in a table that lacks the circumstance is so minimal it could almost be said to never have happened.
Management of the data predominantly refers to how you search through it to find what you need, but since I've covered that above I'll more right to cutting down repeats and such. Good coding means you'll never have the same entry twice, so cutting down instead refers here to removing entries that are no-longer relevant or needed. Management of the database is necessary because of some easy math we can do right now.
Let's say we start off wholesale with 10,000 entries, determining the different actions and circumstances associated. Next, let's assume for each circumstance we've considered each action at least once, and that there are 5 actions (Left, right, forward, back, turn etc.). Then, in our stage 2 circumstance tables, let's assume we have about 50 entries each. Therefore overall we have (10000/5)/50 entries in the super-array. That's 40 entries, not much until you consider that for all the irrelevant or otherwise meaningless entries we still have to sort through all 40 of them when looking for previous data, that means each entry is more time it takes for an action to be considered or added. Culling the herd makes the gBrain faster and less memory heavy.
This is a tricky thing, because you're essentially programming "forgetfulness" into your system, which is an odd idea at the best of times. The best way I can think of is to include a reference array of the entries and when they were last modified. Then, every so often, run through the reference array checking the oldest entries. Obviously if we flat-out erased the oldest data, we could "forget" not to stick our hands in an open flame or to take a blind leap off a cliff.
Instead, before outright deleting something, instead first consider it's modifier. A strong modifier either way (Yes/No) should mean that this is something the brain has encountered often enough to decide firmly what to do in that situation, meaning something it definitively needs to do or avoid doing. This is an entry we don't want to lose, because we would then risk future operation safety.
Therefore instead delete entries with modifiers closer to zero on both counts, these are ones we've either encountered little or that are reasonably neutral on going either way anyway. Remember: Creating a new entry is resource-free, as is not finding an entry in the database. And the smaller the database is kept, the faster the neuron can decide what to do.
Monday, 25 January 2010
Gmod Brain #2
Here's the basic construct I'm looking at for a given neuron.
When the control center sends out a "decision" signal, the neuron checks the incoming relevant variables from global variables, the precise number of which it gets from gGetNum(1) then counts upwards from there. For example, if the 1st gVar tells the neuron that there are 8 variables to acquire, it gets gVars 2-9 and stores them in together in a string separated by "-". gVar(2) is always the action to be undertaken in a string dialect (Such as "turnLeft", "turnRight", "Reverse", etc.)
The neuron then checks it's existing storehouse table of variable strings, to see if it's encountered the same circumstances before. It adds the modifier from that string reference to it's eventual result.
What occurs next is basically a random reaction. The neuron generates a random number from 0 to 1, adds the modifier, and rounds to 0 or 1 exactly. If it gets a 1, it sends out a "good" signal, and if it gets a 0, it sends out a "bad" signal.
The control center, which sets the number in gVar 1 and collects all the relevant good/bad signals, then tallies which state wins out and informs the operating body.
Meanwhile, the neuron waits until either it receives another "decision" signal or it receives a "pos" or "neg" signal. If it gets a "neg", it subtracts -0.1 (for example) from the stored modifier for the variable string in the storehouse, and adds 0.1 if it instead gets a "pos". Therefore, the neuron becomes less likely (but not unable) to choose the same bad idea twice and more likely to choose the same good idea twice.
Of course, this isn't by any means a perfect simulation of organic thinking, because in the words of Carl Sagan "The brain does more than just recollect, it intercompares, it synthesises, it analyses, it generates abstractions."
That of course is the next stage, once the neurons and control center can be properly composed for separate action types like motion and pathfinding etc.
When the control center sends out a "decision" signal, the neuron checks the incoming relevant variables from global variables, the precise number of which it gets from gGetNum(1) then counts upwards from there. For example, if the 1st gVar tells the neuron that there are 8 variables to acquire, it gets gVars 2-9 and stores them in together in a string separated by "-". gVar(2) is always the action to be undertaken in a string dialect (Such as "turnLeft", "turnRight", "Reverse", etc.)
The neuron then checks it's existing storehouse table of variable strings, to see if it's encountered the same circumstances before. It adds the modifier from that string reference to it's eventual result.
What occurs next is basically a random reaction. The neuron generates a random number from 0 to 1, adds the modifier, and rounds to 0 or 1 exactly. If it gets a 1, it sends out a "good" signal, and if it gets a 0, it sends out a "bad" signal.
The control center, which sets the number in gVar 1 and collects all the relevant good/bad signals, then tallies which state wins out and informs the operating body.
Meanwhile, the neuron waits until either it receives another "decision" signal or it receives a "pos" or "neg" signal. If it gets a "neg", it subtracts -0.1 (for example) from the stored modifier for the variable string in the storehouse, and adds 0.1 if it instead gets a "pos". Therefore, the neuron becomes less likely (but not unable) to choose the same bad idea twice and more likely to choose the same good idea twice.
Of course, this isn't by any means a perfect simulation of organic thinking, because in the words of Carl Sagan "The brain does more than just recollect, it intercompares, it synthesises, it analyses, it generates abstractions."
That of course is the next stage, once the neurons and control center can be properly composed for separate action types like motion and pathfinding etc.
Monday, 18 January 2010
Ragdoll Zombie
Ragdolls are pretty fun to mess around with, but something I've yet to see much is using them with expression 2's applyForce in almost any fashion. So I've been putting together a basic little thing that may become the new Hel or Loki drone for Valhalla.
Basically, you plant this code onto any ragdoll (Preferably a human HL2 character because that's what the variables are based on and they're pretty consistent), the ragdoll hops up and starts following you. The name comes from the brief programming that self-destructs the E2 chip if you open fire on the zombie's head (Though the chip itself is also fair game); anywhere else and it just keeps coming. It's a work in progress so there's a few kinks to it (Like being able to kill a zombie from across the map with the crowbar...).
As I said this might be the basis for a drone, so there's a little droid head that also shows up above the ragdoll and stares at you, the end product might float the E2 inside the head and search for ragdolls to use as "human shields" for itself.
Code:
@name Ragdoll Zombie prototype
@persist E:entity N Mass Z BC
if(first()){
E=entity():isWeldedTo()
BC=E:boneCount()
entity():setAlpha(255)
entity():setMass(0)
OT=owner():toWorld(owner():boxMax()):z()
OB=owner():toWorld(owner():boxMin()):z()
Z=(OT-OB)
#Pelvis = 0
#Torso = 1
#RShoulder = 2
#LShoulder = 3
#LElbow = 4
#LHand = 5
#RElbow = 6
#RHand = 7
#Hip = 8
#Knee = 9
#Head = 10
Ang=array() Col=array() Mod=array() Par=array() Pos=array() Sca=array()
Ang:pushAngle(ang()) Col:pushVector(vec(1,1,1)*255) Mod:pushString("hqicosphere2") Par:pushNumber(0) Pos:pushVector(vec(0,0,23)) Sca:pushVector(vec(2,1.5,1)/2)
Ang:pushAngle(ang()) Col:pushVector(vec(0,1,1)*255) Mod:pushString("dome2") Par:pushNumber(1) Pos:pushVector(vec(2,0,25)) Sca:pushVector(vec(2,2,1)/2)
Ang:pushAngle(ang(-22.5,0,0)) Col:pushVector(vec(0,1,1)*255) Mod:pushString("dome2") Par:pushNumber(1) Pos:pushVector(vec(-1,0,24)) Sca:pushVector(vec(2,2,1)/2)
Ang:pushAngle(ang(-45,0,0)) Col:pushVector(vec(0,1,1)*255) Mod:pushString("dome2") Par:pushNumber(1) Pos:pushVector(vec(-3,0,23)) Sca:pushVector(vec(2,2,1)/2)
Ang:pushAngle(ang(90,0,0)) Col:pushVector(vec(0,1,1)*255) Mod:pushString("hqcylinder") Par:pushNumber(1) Pos:pushVector(vec(2,0,23)) Sca:pushVector(vec(1,1,3)/4)
M=0
while(M<=Ang:count()){
P=Pos[M,vector]+E:bone(10):pos()
S=Sca[M,vector]
A=Ang[M,angle]
C=Col[M,vector]
Mo=Mod[M,string]
holoCreate(M,P,S,A,C)
holoModel(M,Mo)
if(Par[M,number]){holoParent(M,Par[M,number])}
M++
}
runOnTick(1)
}
while(N<=BC){
B=E:bone(N)
Mass+=B:mass()
N++
}
rangerFilter(E)
Ground=rangerOffset(2000,E:bone(1):massCenter(),vec(0,0,-1)):position()
O=owner():toWorld(owner():boxCenter())
Po=Ground+vec(0,0,Z-7)
Vec=(Po-E:bone(1):massCenter())*(Mass+20)
E:bone(1):applyForce(Vec)
E:bone(1):applyForce((owner():pos()-E:bone(1):pos()):normalized()*50)
Po=E:bone(1):pos()+vec(0,0,10)
Vec=(Po-E:bone(10):massCenter())*E:bone(10):mass()
E:bone(10):applyForce(Vec)
Skull=E:bone(10):pos():setZ((E:toWorld(E:boxMax())+vec(0,0,5)):z())
holoPos(1,Skull)
holoAng(1,(owner():shootPos()-holoEntity(1):pos()):toAngle())
Po=E:bone(1):pos()-vec(0,0,10)
Vec=(Po-E:bone(0):massCenter())*E:bone(0):mass()
E:bone(0):applyForce(Vec)
E:bone(0):applyForce((owner():pos()-E:bone(0):pos()):normalized()*50)
if((owner():aimBone()==E:bone(10)|owner():aimEntity()==entity())
& owner():keyAttack1()){
selfDestruct()
}
Basically, you plant this code onto any ragdoll (Preferably a human HL2 character because that's what the variables are based on and they're pretty consistent), the ragdoll hops up and starts following you. The name comes from the brief programming that self-destructs the E2 chip if you open fire on the zombie's head (Though the chip itself is also fair game); anywhere else and it just keeps coming. It's a work in progress so there's a few kinks to it (Like being able to kill a zombie from across the map with the crowbar...).
As I said this might be the basis for a drone, so there's a little droid head that also shows up above the ragdoll and stares at you, the end product might float the E2 inside the head and search for ragdolls to use as "human shields" for itself.
Code:
@name Ragdoll Zombie prototype
@persist E:entity N Mass Z BC
if(first()){
E=entity():isWeldedTo()
BC=E:boneCount()
entity():setAlpha(255)
entity():setMass(0)
OT=owner():toWorld(owner():boxMax()):z()
OB=owner():toWorld(owner():boxMin()):z()
Z=(OT-OB)
#Pelvis = 0
#Torso = 1
#RShoulder = 2
#LShoulder = 3
#LElbow = 4
#LHand = 5
#RElbow = 6
#RHand = 7
#Hip = 8
#Knee = 9
#Head = 10
Ang=array() Col=array() Mod=array() Par=array() Pos=array() Sca=array()
Ang:pushAngle(ang()) Col:pushVector(vec(1,1,1)*255) Mod:pushString("hqicosphere2") Par:pushNumber(0) Pos:pushVector(vec(0,0,23)) Sca:pushVector(vec(2,1.5,1)/2)
Ang:pushAngle(ang()) Col:pushVector(vec(0,1,1)*255) Mod:pushString("dome2") Par:pushNumber(1) Pos:pushVector(vec(2,0,25)) Sca:pushVector(vec(2,2,1)/2)
Ang:pushAngle(ang(-22.5,0,0)) Col:pushVector(vec(0,1,1)*255) Mod:pushString("dome2") Par:pushNumber(1) Pos:pushVector(vec(-1,0,24)) Sca:pushVector(vec(2,2,1)/2)
Ang:pushAngle(ang(-45,0,0)) Col:pushVector(vec(0,1,1)*255) Mod:pushString("dome2") Par:pushNumber(1) Pos:pushVector(vec(-3,0,23)) Sca:pushVector(vec(2,2,1)/2)
Ang:pushAngle(ang(90,0,0)) Col:pushVector(vec(0,1,1)*255) Mod:pushString("hqcylinder") Par:pushNumber(1) Pos:pushVector(vec(2,0,23)) Sca:pushVector(vec(1,1,3)/4)
M=0
while(M<=Ang:count()){
P=Pos[M,vector]+E:bone(10):pos()
S=Sca[M,vector]
A=Ang[M,angle]
C=Col[M,vector]
Mo=Mod[M,string]
holoCreate(M,P,S,A,C)
holoModel(M,Mo)
if(Par[M,number]){holoParent(M,Par[M,number])}
M++
}
runOnTick(1)
}
while(N<=BC){
B=E:bone(N)
Mass+=B:mass()
N++
}
rangerFilter(E)
Ground=rangerOffset(2000,E:bone(1):massCenter(),vec(0,0,-1)):position()
O=owner():toWorld(owner():boxCenter())
Po=Ground+vec(0,0,Z-7)
Vec=(Po-E:bone(1):massCenter())*(Mass+20)
E:bone(1):applyForce(Vec)
E:bone(1):applyForce((owner():pos()-E:bone(1):pos()):normalized()*50)
Po=E:bone(1):pos()+vec(0,0,10)
Vec=(Po-E:bone(10):massCenter())*E:bone(10):mass()
E:bone(10):applyForce(Vec)
Skull=E:bone(10):pos():setZ((E:toWorld(E:boxMax())+vec(0,0,5)):z())
holoPos(1,Skull)
holoAng(1,(owner():shootPos()-holoEntity(1):pos()):toAngle())
Po=E:bone(1):pos()-vec(0,0,10)
Vec=(Po-E:bone(0):massCenter())*E:bone(0):mass()
E:bone(0):applyForce(Vec)
E:bone(0):applyForce((owner():pos()-E:bone(0):pos()):normalized()*50)
if((owner():aimBone()==E:bone(10)|owner():aimEntity()==entity())
& owner():keyAttack1()){
selfDestruct()
}
Friday, 15 January 2010
The Brain of Gmod
This is something I'm working on at the moment, it's not finished and mostly I'm still figuring out how to do it.
Basically, a bunch of chips (Or, if I sort out the data storage issues, one or two with loops) talk to a master chip. The master chip takes queries from an outside source like a drone and asks the other chips, based on the available and appropriate variables, whether the suggested course of action should be undertaken.
The chips roll a random number and plus/minus an altering number from an archive of actions it has already done, the master chip collects all these yes/no votes and tells the drone whether or not to do it.
If the action does well for the drone or makes it trip into harm, the appropriate good/bad signal is sent from the master chip and each of the other chips adds/subtracts from it's archived altering number for that scenario.
What this means essentially is that the bunch of chips each have a random possibility of giving the right or wrong response, modified by whether such an action has been successful in the past. I'm calling it an artificial neural network as far as I can personally achieve but it's more like a democratic vote on what the drone should do.
The end result either way is that the brain favours actions that are successful and downplays actions that result in harm, but is still able to take an unforeseen path. Downside here is that to cover the general gist of scenarios takes a while for the drone to encounter them, meaning the brain takes a lot of time to learn the basics and such before it moves on to other things.
Problems:
So my biggest concern is cutting down the combinations so that the chips can actually handle it. I keep thinking in terms of using an array of GLON strings, so I can GLON encode a large table and store it in the array, then decode it temporarily and check if the scenario is stored there.
Basically, a bunch of chips (Or, if I sort out the data storage issues, one or two with loops) talk to a master chip. The master chip takes queries from an outside source like a drone and asks the other chips, based on the available and appropriate variables, whether the suggested course of action should be undertaken.
The chips roll a random number and plus/minus an altering number from an archive of actions it has already done, the master chip collects all these yes/no votes and tells the drone whether or not to do it.
If the action does well for the drone or makes it trip into harm, the appropriate good/bad signal is sent from the master chip and each of the other chips adds/subtracts from it's archived altering number for that scenario.
What this means essentially is that the bunch of chips each have a random possibility of giving the right or wrong response, modified by whether such an action has been successful in the past. I'm calling it an artificial neural network as far as I can personally achieve but it's more like a democratic vote on what the drone should do.
The end result either way is that the brain favours actions that are successful and downplays actions that result in harm, but is still able to take an unforeseen path. Downside here is that to cover the general gist of scenarios takes a while for the drone to encounter them, meaning the brain takes a lot of time to learn the basics and such before it moves on to other things.
Problems:
- Do I have a set selection of possible actions, or do I leave it freeform somehow and make the brain able to work with almost anything?
- Do I break the different scenarios into types (Such as motion, targetting, and homeostasis) or have every scenario be considered by all the neurons?
- With the sheer number of scenarios in a decently complex system, the number of possible combinations the different variables can achieve means the archive storage space quickly becomes massive and untenable. Expression 2s simply don't have the space to take such a mass.
So my biggest concern is cutting down the combinations so that the chips can actually handle it. I keep thinking in terms of using an array of GLON strings, so I can GLON encode a large table and store it in the array, then decode it temporarily and check if the scenario is stored there.
Wednesday, 13 January 2010
Valkyrie Radio
As noted in the opening post, I made something called the Valkyrie radio system. Since this is a perfect example of the cool and/or odd stuff I come up with on a whim in Gmod, I suppose it's a fitting first addition to this blog.
I was considering the upcoming redesign on a lot of my drones and one of their important elements is that they can communicate needs and requirements by text strings, but before they just used the chat and would flood it quite rapidly, making it unusable to players. My thought then was to create a kind of separate chat that the different drones could use different parts of, to talk to different drones and all the drones of their kind as well. A Hephaestus drone could issue a request to the Hermes drone chat after finding out from another Hephaestus on it's chat that it's missing a component for something.
I was considering the upcoming redesign on a lot of my drones and one of their important elements is that they can communicate needs and requirements by text strings, but before they just used the chat and would flood it quite rapidly, making it unusable to players. My thought then was to create a kind of separate chat that the different drones could use different parts of, to talk to different drones and all the drones of their kind as well. A Hephaestus drone could issue a request to the Hermes drone chat after finding out from another Hephaestus on it's chat that it's missing a component for something.
Welcome to Garry's Madness
(The name may imply it but there is no "Garry" working here I'm afraid, merely one rather strange Garry's Mod player)
I'm Tim, and besides making the webcomic Remember I'm also a very avid player of the aforementioned Garry's Mod.
Garry's Mod is a modification of the Half Life 2 Source engine, producing a sandbox in which others can do pretty much anything. At a basic level it's rather simple stuff mostly, like cars composed of bathtubs, but more advanced things have occured such as entire mechs.
However to get a very spectacular level of complexity you need to have the additional addon to the mod known as Wiremod, which allows for things like holograms and complex calculations, at which point what you make and how is virtually unlimited.
What I'm most in/famous for making is drones, contraptions that move around and make decisions by themselves without input from the player, especially on a complex level, and I'm certainly most infamous for working on the Cronus drone, a contraption that can hunt down players and was composed entirely of random props it discovered around the map. Whilst I do tend to make a lot of drones, I do make other things however, such as the Valkyrie radio system, which allows different groups of players to have private chats in relative secrecy.
Specific to this blog, updates will likely be irregular and sporadic, so check back often to see new stuff popping up.
I'm Tim, and besides making the webcomic Remember I'm also a very avid player of the aforementioned Garry's Mod.
Garry's Mod is a modification of the Half Life 2 Source engine, producing a sandbox in which others can do pretty much anything. At a basic level it's rather simple stuff mostly, like cars composed of bathtubs, but more advanced things have occured such as entire mechs.
However to get a very spectacular level of complexity you need to have the additional addon to the mod known as Wiremod, which allows for things like holograms and complex calculations, at which point what you make and how is virtually unlimited.
What I'm most in/famous for making is drones, contraptions that move around and make decisions by themselves without input from the player, especially on a complex level, and I'm certainly most infamous for working on the Cronus drone, a contraption that can hunt down players and was composed entirely of random props it discovered around the map. Whilst I do tend to make a lot of drones, I do make other things however, such as the Valkyrie radio system, which allows different groups of players to have private chats in relative secrecy.
Specific to this blog, updates will likely be irregular and sporadic, so check back often to see new stuff popping up.
Subscribe to:
Posts (Atom)
