Glon certainly ensures the array gets through, but it still has the odd issue of jittery movement from overusing the pathfinder.
EDIT: Managed to get it reasonably effective. The indicator holo now follows me around pretty well on gm_construct and I'm actually having a bit of trouble escaping it, though it's still stopping here and there for some unknown reason (Comp=1, Route is filled, but Pos doesn't change for some reason)Also had to add a little snip of code into the pathfinder (if(Dest:distance(Start)<=Deg){Comp=1} to line 104) which ensures very well that the pathfinder doesn't corrode itself when you, for example, walk through the holo, resulting in a loop that makes an infinitely long output array full of vec(0.0,0.0,0.0) and, by extension, MASSIVE lag.Code:@name Cronus motion and pathfinding control @inputs Path:string Comp @outputs [Loc Dest]:vector @persist Pos:vector O:entity Route:array Copy #debugging outputs @outputs Pos:vector Route:array if(first()){ Pos=entity():pos() Pos/=32 Pos=round(Pos)*32 Pos+=vec(0,0,32) Loc=Pos O=owner() Dest=O:toWorld(O:boxCenter()) Dest/=32 Dest=round(Dest)*32 holoCreate(1,Pos) holoScaleUnits(1,vec(1,1,1)*32) holoAlpha(1,170) runOnTick(1) } if(Comp){ if(!Copy){ Route=glonDecode(Path) Copy++ } Box=O:toWorld(O:boxCenter()) Box=round(Box/32)*32 #Moves the holo along the path Clip=rangerOffset(Pos,Box):entity()==O Clip=Clip & !O:inNoclip() if(Route:count() & Pos:distance(Box)>64){ Node=Route[1,vector] Off=(Node-Pos):normalized() Off*=min(10,Pos:distance(Node)) Pos+=Off if(Pos==Node){ Route:remove(1) } } elseif(Clip){ Off=(Box-Pos):normalized() Off*=min(10,Box:distance(Pos)) Pos+=Off if(Box:distance(Pos)<64){ Off=Pos-Box Off=Off:normalized():setZ(0) Off*=64-Box:distance(Pos) Pos+=Off } } holoPos(1,rangerOffset(500,Pos,vec(0,0,-1)):position()) #Redetermines the path if a break is detected for(N=1,Route:count() & Copy){ if(!perf()){break} A=Route[N,vector] B=(N==1 ? Pos : Route[N-1,vector]) R=rangerOffset(B,A) if(R:hit()){ Loc=Pos Copy=0 } } #Redetermines the path if the target has sufficiently moved R=rangerOffset(Box,Loc) Check=!R:hit() Check=(!Check ? Box:distance(Dest)>(32*5) : Check) if(Check & Copy){ Dest=Box R=rangerOffset(500,Pos,vec(0,0,-1)) Loc=round(R:position()/32)*32+vec(0,0,16) Copy=0 } }
Once the motion is fully coded and at least reasonably-bug free, I'll have the positioner code connect to the motion control chip here and position the props appropriately, then I'll update my original prop-finder code to get it running as smoothly as possible, add in fire control, and we have ourselves a pretty dang awesome drone. After that, it's pretty much all addons and filler.
Last edited by Lyinginbedmon; 09-02-2010 at 07:13 AM.
SVN Tutorial
My SVN:Get dropbox and get 250 MB extra space: DropboxCode:http://divranspack.googlecode.com/svn/trunk/%20divranspack/
WIPCode:@name Cronus entity discovery optics @inputs O:entity @outputs [Props Tar]:array @persist [Props Dir Known Tar]:array @persist NMin Min NMax Max P if(first()){ O=owner() #O is the sclera holoentity of the Eye of Cronus #Here owner is used for testing purposes Dir:pushVector(vec(1,0,0)) Dir:pushVector(vec(0,1,0)) Dir:pushVector(vec(0,0,1)) Dir:pushVector(vec(-1,0,0)) Dir:pushVector(vec(0,-1,0)) Dir:pushVector(vec(0,0,-1)) Min=O:id() Max=Min Known[Min,number]=1 runOnTick(1) } #Local Eye vision rangerFilter(O) Box=O:toWorld(O:boxCenter()) for(N=1,Dir:count()){ V=Dir[N,vector]:rotate(O:angles()) R=rangerOffset(1000,Box,V) if(R:entity()){ ID=R:entity():id() NMin=min(Min,ID) NMax=max(Max,ID) } } #World Entity vision rangerFilter(Props) while(P<Props:count() & perf()){ E=Props[P,entity] Box=E:toWorld(E:boxCenter()) for(N=1,Dir:count()){ V=Dir[N,vector]:rotate(E:angles()) R=rangerOffset(1000,Box,V) if(R:entity()){ ID=R:entity():id() NMin=min(NMin,ID) NMax=max(NMax,ID) } holoPos(N,R:position()) } P++ } if(P>=Props:count()){P=1} Count=Props:count() #Entity seeking #Minimum entity ID for(N=Min,NMin,-1){ E=entity(N) if(E & !Known[N,number]){ if(E:isPlayer()|E:isNPC()){ Tar:pushEntity(E) } elseif(E:type():find("prop")){ Props:pushEntity(E) holoCreate(N,E:pos()+vec(0,0,20)) holoParent(N,E) } Known[N,number]=1 } } Min=NMin #Maximum entity ID for(N=Max,NMax){ E=entity(N) if(E & !Known[N,number]){ if(E:isPlayer()|E:isAdmin()){ Tar:pushEntity(E) } elseif(E:type():find("prop")){ Props:pushEntity(E) holoCreate(N,E:pos()+vec(0,0,20)) holoParent(N,E) } Known[N,number]=1 } } Max=NMax
Nice code, any chance you could talk me/us through what each stage is doing? 1. sends a trace out from the eye in each cardinal direction to locate new props, right? 2. then does it take every known prop and do the same from that prop?
Also, what does perf() do?
Local eye vision is the preset direction trace from the eye, yes.
It then indeed does the same thing from every prop the optics has discovered.
Through all of those traces, it checks the entity ID of whatever entities it hits (ignoring entities it has already hit), and compares it to a Max and Min (NMax and NMin being the latest high and low of an execution). The Known array just keeps it from adding ones it's already hit (I'm not sure why it's needed but it keeps it from running into excesses for some reason)
It then scans through the entity IDs from it's existing Max and Min to those new values to find new targets (players and NPCs) and new props to add to the list. Consequently, as the optics find more and more props its capacity for finding new props and targets increases exponentially. If it doesn't find a given entity by traces, it will find it by ID eventually as the drone moves around.
perf() regulates the while loop to the absolute maximum the chip can sustain, allowing it to run through as many props as possible each execution. The same thing is used in the pathfinder.
Hmmm.. seems a bit odd that it can see from every prop it can see. Its like every prop it knows about suddenly becomes its eyes. How does perf() do it? does it just quit the while loop or, pause it or what?
perf() returns 1 or 0 depending on whether the chip can continue or not without redchipping.
E2 is awesome <3
Right, I didn't have the Internet for the past two weeks but I did spend some time working on the motion control and Cronus Eye graphics, the result being something I think will be rather well received, however a couple days ago my computer got hit by a sleeper virus and is presently in the process of being repaired (I'm currently using a desktop with near zero HDD space in the family dining room on a copy of IE that predates not only tabbing but also image transparency...hello again 90s, it's been so long) so I unfortunately can't present it to you all at this time.
Promise to do ASAP though, the lack of problem solving available to me at the moment is seriously driving me batty.
RE: The graphics, I've combined the Eye itself into the Cronus project logo as one chip. The idea being the logo denotes where the drone will start off after activation, and the Eye is kept inside the upper spheroid section otherwise. The sphere occasionally flickers with electrical noises and the tossing around of a random nearby prop too, to give a rather nice aesthetic of the drone within.
The Olympus Technologies drones, totally not SkyNet in Gmod form.
Cronus: The Ultimate Drone, definitely SkyNet in Gmod form.
The gBrain Project, the drone controls system that thinks it's better than you
Here we go then, my laptop is repaired and presently running through one last virus scan before returning to full normal functions, and here's the two codes I've spent most of my downtime toying with.The motion control chip currently only follows the Owner, but it won't take much to modify it for larger target groups once the targetting code is done.Code:@name CRONUS motion and pathfinding control mk 2 @inputs Path:string Comp @outputs [GPS1 GPS2]:vector @persist Pos:vector O:entity Route:array Copy RC if(first()){ Pos=entity():pos() Pos/=32 Pos=round(Pos)*32 Pos+=vec(0,0,32) GPS1=Pos O=owner() GPS2=O:toWorld(O:boxCenter()) GPS2/=32 GPS2=round(GPS2)*32 runOnTick(1) } if(Comp){ if(!Copy){ Route=glonDecode(Path) RC=0 Copy++ } Box=O:toWorld(O:boxCenter()) Box=round(Box/32)*32 #Moves the holo along the path Clip=rangerOffset(Pos,Box):entity()==O & !O:inNoclip() if(Route:count() & Pos:distance(Box)>64){ Node=Route[1,vector] Off=(Node-Pos):normalized() Off*=min(4,Pos:distance(Node)) Pos+=Off if(Pos==Node){ Route:remove(1) RC++ } } elseif(Clip){ Off=(Box-Pos):normalized() Off*=min(10,Box:distance(Pos)) Pos+=Off if(Box:distance(Pos)<64){ Off=Pos-Box Off=Off:normalized():setZ(0) Off*=64-Box:distance(Pos) Pos+=Off } } #Redetermines the path if a break is detected rangerFilter(O) for(N=1,Route:count() & Copy){ if(!perf()){break} A=Route[N,vector] B=(N==1 ? Pos : Route[N-1,vector]) R=rangerOffset(B,A) if(R:hit()){ R=rangerOffset(500,Pos,vec(0,0,-1)) GPS1=round(R:position()/32)*32+vec(0,0,16) Pos=GPS1 Copy=0 } } #Redetermines the path if the target has sufficiently moved if(RC>=(Route:count()/2)){ R=rangerOffset(Box,GPS1) Check=!R:hit() | Box:distance(GPS2)>(32*5) if(Check & Copy){ GPS2=Box R=rangerOffset(500,Pos,vec(0,0,-1)) GPS1=round(R:position()/32)*32+vec(0,0,16) Copy=0 } RC=0 } }The visual basis chip is unique in that it doesn't require any external Cronus chips connected to perform the majority of it's functions, you can pretty much just drop it anywhere you want and it'll be fine. It's only when it's connected to the other chips that it's full potential get's unlocked though.Code:@name CRONUS visual basis @inputs Active [Point Look]:vector Light:wirelink @persist Turn B Mat @persist [Ents Zaps]:array @persist [H1 H7]:entity if(first()){ Turn=(round(random()) ? 1 : -1) Pos=array(),Sca=array(),Angle=array(),Model=array(),Colour=array() Pos:pushVector(vec()),Sca:pushVector(vec(12.5,12.5,12.5)),Angle:pushAngle(ang()),Model:pushString("hqicosphere2"),Colour:pushVector(vec(60,165,255)) Pos:pushVector(vec()),Sca:pushVector(vec(13,13,13)),Angle:pushAngle(ang(90,0,0)),Model:pushString("hqtorus2"),Colour:pushVector(vec()) Pos:pushVector(vec(0,0,-20)),Sca:pushVector(vec(3.75,3.75,30.5)),Angle:pushAngle(ang(0,90,0)),Model:pushString("hqcylinder2"),Colour:pushVector(vec(60,165,255)) Pos:pushVector(vec(0,-7.6,-20)),Sca:pushVector(vec(3.125,3.125,18.75)),Angle:pushAngle(ang(62,90,0)),Model:pushString("hqcylinder2"),Colour:pushVector(vec(60,165,255)) Pos:pushVector(vec(0,-14.8,-28.7)),Sca:pushVector(vec(3.125,3.125,11.25)),Angle:pushAngle(ang(0,90,0)),Model:pushString("hqcylinder2"),Colour:pushVector(vec(60,165,255)) Pos:pushVector(vec(0,-13,-38)),Sca:pushVector(vec(3.125,3.125,31.25)),Angle:pushAngle(ang(70,90,0)),Model:pushString("hqcylinder2"),Colour:pushVector(vec(60,165,255)) Pos:pushVector(vec(0,-26.2,-54.5)),Sca:pushVector(vec(3.125,3.125,25)),Angle:pushAngle(ang(0,90,0)),Model:pushString("hqcylinder2"),Colour:pushVector(vec(60,165,255)) Pos:pushVector(vec(0,-11,-43)),Sca:pushVector(vec(3.125,3.125,12.5)),Angle:pushAngle(ang(0,90,0)),Model:pushString("hqcylinder2"),Colour:pushVector(vec(60,165,255)) Pos:pushVector(vec(0,9,-32)),Sca:pushVector(vec(3.125,3.125,25)),Angle:pushAngle(ang(-50,90,0)),Model:pushString("hqcylinder2"),Colour:pushVector(vec(60,165,255)) Pos:pushVector(vec(0,17.5,-48.5)),Sca:pushVector(vec(3.125,3.125,20)),Angle:pushAngle(ang(0,90,0)),Model:pushString("hqcylinder2"),Colour:pushVector(vec(60,165,255)) for(N=1,10){ H=entity():id()+N holoCreate(H) holoPos(H,entity():pos()+Pos[N,vector]*2.85) holoScaleUnits(H,Sca[N,vector]*2.85) holoAng(H,Angle[N,angle]) holoModel(H,Model[N,string]) holoColor(H,Colour[N,vector]) holoShadow(H,0) } B=entity():id()+2 for(N=(B+1),B+8){ holoParent(N,B) } Zaps:pushString("ambient/energy/zap1.wav") Zaps:pushString("ambient/energy/zap2.wav") Zaps:pushString("ambient/energy/zap3.wav") Zaps:pushString("ambient/energy/zap4.wav") Zaps:pushString("ambient/energy/zap5.wav") Zaps:pushString("ambient/energy/zap6.wav") Zaps:pushString("ambient/energy/zap7.wav") Zaps:pushString("ambient/energy/zap8.wav") Zaps:pushString("ambient/energy/zap9.wav") findIncludeClass("prop_physics") timer("rand",1000*random()) timer("eyespawn",3*1000) runOnTick(1) } if(clk("eyespawn")){ Angles=array(),Colours=array(),Materials=array(),Models=array(),Parents=array(),Positions=array(),Scales=array() #Creation array populating Angles[1,angle]=ang(270,0,0),Angles[2,angle]=ang(),Angles[3,angle]=ang(40,90,90),Angles[4,angle]=ang(-40,90,90),Angles[5,angle]=ang(45,40,0),Angles[6,angle]=ang(-45,-40,0),Angles[7,angle]=ang(0,90,0) Colours[1,vector]=vec(0,1,1)*191.25,Colours[2,vector]=vec(0,1,1)*255,Colours[3,vector]=vec(1,1,1)*255,Colours[4,vector]=vec(1,1,1)*255,Colours[5,vector]=vec(1,1,1)*255,Colours[6,vector]=vec(1,1,1)*255,Colours[7,vector]=vec(0,1,1)*255 Models[1,string]="hqicosphere2",Models[2,string]="hqicosphere2",Models[3,string]="hqcylinder",Models[4,string]="hqcylinder",Models[5,string]="hqcylinder",Models[6,string]="hqcylinder",Models[7,string]="hqicosphere2" Parents[1,number]=7,Parents[2,number]=1,Parents[3,number]=7,Parents[4,number]=7,Parents[5,number]=7,Parents[6,number]=7,Parents[7,number]=7 Positions[1,vector]=vec(),Positions[2,vector]=vec(0,0,1),Positions[3,vector]=vec(0,-3,-7),Positions[4,vector]=vec(0,-3,6),Positions[5,vector]=vec(-7,-4,6),Positions[6,vector]=vec(7,-4,6),Positions[7,vector]=vec(0,-4,0) Scales[1,vector]=vec(2,2,2)/3,Scales[2,vector]=vec(3,3,6)/9,Scales[3,vector]=vec(1,4,1)/3,Scales[4,vector]=vec(1,4,1)/3,Scales[5,vector]=vec(4,1,1)/3,Scales[6,vector]=vec(4,1,1)/3,Scales[7,vector]=vec(1,5,4)/3 #Creation arrays ditched after first execution #Hologram production #Spawning for(S=1,Positions:count()){ Position=Positions[S,vector] Scale=Scales[S,vector] Ang=Angles[S,angle] Col=Colours[S,vector] holoCreate(S,Position,Scale,Ang,Col) holoModel(S,Models[S,string]) if(S==7){holoMaterial(7,"models/props_combine/tpballglow")} } #Parenting for(P=1,Positions:count()){ holoParent(P,Parents[P,number]) } H1=holoEntity(1) H7=holoEntity(7) } #Symbol rotation Ang=holoEntity(B):angles() Ang += ang(0,Turn*2.5,0) holoAng(B,Ang) #Symbol positioning Sym = entity():pos()+vec(0,0,199.5) holoPos(B-1,Sym) holoPos(B,Sym) #Light positioning Lum=Light:entity() if(Lum){ Box=Lum:toWorld(Lum:boxCenter()) Vect=Sym-Box Vect*=Lum:mass() Vect-=Lum:vel()/2 Lum:applyForce(Vect) Q=quat(ang())/quat(Lum) T=Lum:toLocal(rotationVector(Q)+Box) T=((T*1000) -Lum:angVelVector()*20) Lum:applyTorque(T) } #Containment flickering if(clk("rand")){ if(Mat & !Active){ holoMaterial(B-1,"") Lum:setAlpha(0) Light["RGB",vector]=vec() Num=10000 } elseif(holoEntity(1)){ holoMaterial(B-1,"models/alyx/emptool_glow") Lum:setAlpha(255) Light["RGB",vector]=vec(1,1,1)*255 Zap=Zaps[round(random(1,9)),string] holoEntity(B-1):soundPlay(1,1,Zap) soundVolume(1,1/10) Num=500+(Active*9500) if(!Active){ if(findCanQuery() & clk("rand")){ findInSphere(Sym,1000) findSortByDistance(Sym) Ents=findToArray() } Ent=Ents[round(random(1,Ents:count())),entity] if(Ent & !Ent:isFrozen() & !Ent:hasConstraints()){ Vec=randvec(vec(-1,-1,0),vec(1,1,1)) Vec*=min(Ent:mass(),5000) Ent:applyForce(Vec) } } } elseif(!Active){ Num=500 } Mat=(Active ? 0 : !Mat) timer("rand",Num*random()) } #Activation controls if(Active){ if(changed(Active)){ holoEntity(B):soundPlay(1,1,"ambient/machines/floodgate_stop1.wav") holoMaterial(B-1,"models/alyx/emptool_glow") } } elseif(Active<0){ selfDestruct() } ########################## # Eye Function # ########################## #Hovering if(Point & Active){Po=Point}else{Po=Sym} holoPos(7,Po) #Look position if(!Look|!Active){ T=Sym+vec(10,0,0):rotate(Ang:setPitch(0)) } else{ T=Look } if(!Look & $Look){reset()} #Prevents angle locking if the Eye chip is destroyed #Eye turning A=(T-H1:pos()):toAngle() holoAng(1,A) #Main body turning (25 times slower) A7=(T-H7:pos()):toAngle()-H7:angles() C=(H7:angles()+A7/25):setRoll(0) holoAng(7,C)
Last edited by Lyinginbedmon; 09-21-2010 at 07:44 AM.
The Olympus Technologies drones, totally not SkyNet in Gmod form.
Cronus: The Ultimate Drone, definitely SkyNet in Gmod form.
The gBrain Project, the drone controls system that thinks it's better than you
Lyinginbedmon's Handy Dandy Progress Report
- Activation
- Controls the Active input of the chips and handles the moderating and voting systems to de/activate the drone
- Done, add aesthetic holos to screen and/or change to console screen (presently text screen)?
- Body composition
- Finds appropriate props from Optics for missing body slots according to it's own checks and the return from Targetting
- Done (?)
- Body control
- Pushes and orients the body props from Body composition into their calculated places, outputs the "head" location to Visuals
- In Dev
- Motion control
- Moves the drone along the path output from Pathfinding and determines when to recalculate the path
- Done
- Optics
- Discerns new props for Body composition and new targets for Targetting by ranger tracing through the Aesthetics eye and all discovered props
- Done
- Pathfinding
- Finds traversible routes between the drone and its target destination according to Motion control
- Done, add destination->location (presently just location->destination) and management chips to choose between the two?
- Targetting
- Controls the prop firing systems via the Optics target list and tells Body control what parts to stop affecting on that basis and Body composition which parts are now absent
- Not currently in dev
- Visuals
- Gives a readily-recognisable visual aesthetic to the drone and informs the Optics of the eye position and orientation for scanning
- Done
Last edited by Lyinginbedmon; 09-23-2010 at 05:41 PM.
Bookmarks