Knuckle Cracker

Creeper World 3 => The Coder's Corner => Topic started by: Dook on July 10, 2014, 09:55:05 AM

Title: Remote shield emitter
Post by: Dook on July 10, 2014, 09:55:05 AM
Had an idea where you'd have an enemy unit that technically did nothing but had a unique ID, then another unit that would put up a shield that the player can't land or build units on. When the unique ID unit count reaches zero the shield emitter unit would either be destroyed or become inoperative. The idea is to protect an inhibitor with a shield till all remote shield relays are destroyed. This should be possible right? if any one has some generous free time to make a script i'd be much appreciative. also would it be possible to have the remote relays emit a slight transparent beam to the shield emitter? or some other slight graphical effect? Idea being the player would intuitively know what the remote relays are doing with out having the need to explain anything.

If script requests are frowned upon then i apologize in advance.
Title: Re: Remote shield emitter
Post by: stewbasic on July 10, 2014, 08:10:19 PM
I'll try to put a script together tonight (unless someone beats me to it :P).
Title: Re: Remote shield emitter
Post by: ParkourPenguin on July 10, 2014, 10:51:34 PM
I don't believe script requests are frowned upon. I know I don't mind- I love making scripts!  :D

Anyways, I put together a couple scripts that can do what you asked. Here's a short description of both of them:

AntiUnitShield.crpl:

This is the thing that generates the shield that won't allow player units to land or be built. Please take note of the fact that it uses SetCellOccupiedCount to do this, and I've had some bugs dealing with that "shield" persisting even after the CRPL tower is destroyed. I think I've gotten rid of most of those bugs, but if you come across any, please let me know.
Here's a list and a description of all the variables:









radiusThe shield is shaped like a circle, and this variable sets the radius of that circle in tiles.
maxAmmoThe tower uses ammo to keep track of whether or not it's receiving power from any other towers. Set this value to negative if you want unlimited ammo (it never turns off until it's destroyed).
initialAmmoThis is how much ammo is initially given to the tower. The ammo depletes at a rate of 1 ammo per second, assuming no other tower is supplying it with ammo.
effectThe tower creates an effect around the circle to show the player what area it covers. This sets what effect is displayed. Click here (http://knucklecracker.com/wiki/doku.php?id=crpl:docs:createeffect) to see a list of all available effects.
effectSpeedThis is the magnitude of the tangential velocity of the effect (aka its speed) in pixels per frame as it moves around the circle.
numOfEffectsThis represents how many effects are displayed around the outside of the circle. They are automatically evenly spaced around it.
effectFrameSkipThe CRPL tower will skip this many frames between updating the effects around the tower. If you notice any lag when using these scripts, try increasing this value.


AntiUnitShieldBattery.crpl:

This will supply ammo to whatever tower you specify. It has effects built into it that should travel in a straight line to the tower it is supplying ammo to. Please note that when the main tower that's generating the shield is destroyed, any towers that are supplying it energy will also be destroyed.

Also, I didn't change any unit attributes on this tower, so if you want them changed from their default values, make sure to do that in the "Properties" menu when clicking on the CRPL tower.

Again, here's a list and a description of all the variables:









targetXThe X-Coordinate of the tower it is supposed to supply energy to. This only has to be set once.
targetYThe Y-Coordinate of the tower it is supposed to supply energy to. This only has to be set once.
rateHow much ammo it supplies to the tower every second. Note that the tower depletes ammo when running at a rate of 1 ammo per second.
effectThis sets what effect is displayed as it travels in a line from itself to the target tower. Click here (http://knucklecracker.com/wiki/doku.php?id=crpl:docs:createeffect) to see a list of all available effects.
numOfEffectsThe maximum number of effects that travel along the line at once.
effectSpeedHow fast the effect goes in pixels per frame.
effectFrameSkipThe CRPL tower will skip this many frames between updating the effects around the tower. If you notice any lag when using these scripts, try increasing this value.


I tried to find and fix as many bugs as I could, but it's pretty late where I am now and I'm tired. In case I missed any, please tell me about them so I can fix them.

If you have any questions, please don't hesitate to ask. I'm always happy to help! :)
Title: Re: Remote shield emitter
Post by: Dook on July 11, 2014, 07:11:50 AM
wow awesome. exactly what i had in mind. nice work!

did a bit of testing and did get the bug of persisting shield.
Though everything else seems to be working.
as soon as the shield batterys go down the ammo quickly dissipates and the effects turn off. shield still remains though.
Title: Re: Remote shield emitter
Post by: ParkourPenguin on July 11, 2014, 09:51:53 AM
I found a couple bugs. One dealing with the infinite ammo thing not working- apparently you can't pass a negative value into CONST_MAXAMMO, but I got that fixed by switching that out with the local variable, which actually makes more sense than getting CONST_MAXAMMO.

Beyond that, I found a glitch where the shield wouldn't correctly update if the unit was moved around. This is probably the cause of the persisting shield you were getting. I believe that's fixed now.

You can download the updated version of my script from my previous post. Please let me know if the persisting shield glitch causes you any more trouble.
Title: Re: Remote shield emitter
Post by: Dook on July 11, 2014, 10:59:35 AM
new bug cropped up. looks like a blank error code box right next to the antishieldemitter core. 1 line thick but no text. shield still persists if u move it around enough. but it works when i placed it then didn't touch it again
Title: Re: Remote shield emitter
Post by: Grayzzur on July 11, 2014, 11:12:41 AM
in the AntiUnitShield.crpl file, near the top, if you change "ShowTraceLog" to "HideTraceLog" that trace log box will go away.

The trace log and trace commands are great for debugging a script -- not so much for a finished map!

:)

And yes, this is absolutely the right place to put script requests. As you've discovered, there are plenty of helpful people on this forum willing to give it a go.
Title: Re: Remote shield emitter
Post by: ParkourPenguin on July 11, 2014, 11:26:42 AM
My apologies- I didn't even notice that the trace log was still showing. I've updated the script to not show it anymore.

As for the persisting shield bug, I haven't noticed it at all. If you're able to replicate it, please let me know, and list step-by-step everything you do. That will help me fix it.

Edit:
I think I might have found something. I forgot to set the radius of deleting the previous shield when the tower was moved, so the default radius should work, but anything larger would cause the shield to stay. I've updated the script again with this fix.
Title: Re: Remote shield emitter
Post by: Dook on July 11, 2014, 11:28:03 AM
sweet, thanks  ;D
Title: Re: Remote shield emitter
Post by: Dook on July 12, 2014, 12:49:59 PM
Script is working great and just as i envisioned. thank you. Sense you helped me this far i was wondering if you would want to possibly contribute a bit more? As of now the map is basically complete save the art aspects which i'll do last (terrain and units). Testing it out i realized the nature of the antiunitsheild script lends its self to be able to do a 2 phase map. 1st phase clearing away preplaced units and shield batterys. The 2nd phase could be when the shield goes down a new threat emerges. Something more difficult to give a player with a set up base an actual challenge. Got plenty of spots in the center of the map for CRPL cores. I was thinking maybe some sort of cannon that spits creeper emitters randomly around the map. Although if you got a better idea or some script collecting dust you want to bust out i'm definitely open to suggestions.

If i'm imposing to much trust me now worries. although if you do want to help, take your time, i'm in no rush.

Image to the map so u can see the general idea. again art aspects not done yet.
(http://i.imgur.com/jLqo1V7l.png)
Title: Re: Remote shield emitter
Post by: ParkourPenguin on July 12, 2014, 10:30:00 PM
No worries. As I said previously, I love making scripts!  ;)

By the way, your map looks awesome so far. I love all the detail in the terrain, and with all the CRPL, it looks like it's going to be quite an interesting challenge.

With regards to your request, I made a mortar script a couple days ago that's effectively the creeper's version of the player's mortar. I just had to modify it a little bit for it to spawn an emitter when the projectile lands. Here's a description of both of the scripts required to make this work:

CreeperMortar.crpl:

Not much to say here. Just attach this to a CRPL tower, set all the variables, and it works. I've been playing around with this for a while, and I think I've debugged mostly everything I can, so you shouldn't encounter any bugs.

While this isn't a markedly intricate script, it does have quite a few variables for you to set. Here is a description of each of them:
















mortarIntervalHow many frames the mortar should wait before firing again.
mortarPayloadThe amount of creeper spawned in when the projectile fired by the mortar lands. Set to 0 to not spawn any creeper.
mortarTargetXThe X-Coordinate of the area the mortar is firing at.
mortarTargetYThe Y-Coordinate of the area the mortar is firing at.
mortarTargetRadiusThis is the radius of the circle the mortar's projectile is certain to land in. For example, if this is set to 10, the mortar's projectile could land at X,Y and every tile in a 10-tile radius from it. If this is set to 0, it will always land at X,Y. Note that there is a statistically higher chance for the projectile to hit at the center than at the edge of the circle.
spawnedEmitterProductionAmtThe amount of creeper the emitter will produce when it spawns in after the projectile lands. Set this to 0 if you want emitters to not spawn in when the projectile lands. Also, note that an emitter will not spawn if a unit is already at that tile, so they can't stack.
spawnedEmitterProductionIntervalThe number of frames between each creeper production of the spawned-in emitter.
projectileImageThe location of the image assigned to the projectile as it flies through the air.
projectileSpeedHow fast the projectile goes through the air. If this is set to 0, the tower will not fire any projectiles, and will instead always produce creeper (see triggerRange below).
projectileAngularVelocityThis is the amount of "spin" assigned to the projectile.
projectileUpdateDelayHow quickly the projectile's image is updated as it flies through the air. You should increase this value only if you notice lag when using this script.
triggerRangeIf player units get in a certain range of the CRPL tower this script is attached to, the tower will switch from firing projectiles to producing creeper. This is the maximum range required to trigger this effect. Note that if projectileSpeed is set to 0, this tower will always produce creeper regardless of whether or not there are any units in range.
emitIntervalThe number of frames between each creeper production of this tower.
emitAmountHow much creeper is produced by this tower when it activates.


MortarShell.crpl:

This script is automatically attached to the projectile fired by the actual mortar tower. While you shouldn't attach this to anything normally, feel free to if you want. It's variables should be self-explanatory, especially after reading the previous script's variables; however, if you have any questions about them, just ask, and I'll be more than willing to help!


Just note that with these scripts, you can change the variables in here at any time with another CRPL tower by using SetScriptVar (http://knucklecracker.com/wiki/doku.php?id=crpl:docs:setscriptvar). For instance, if you ever want a mortar to stop creating emitters, just simply set spawnedEmitterProductionAmt to 0 with another CRPL tower.


If you're looking for something else to add, the first script I made was a landmine script. You can click here (http://knucklecracker.com/forums/index.php?topic=16282.0) to go to that topic. Just be warned- you can easily make a player rage if you don't tell him/her about the possibility of landmines.

I'm sure a bunch of other people also have scripts you could implement into your map. Take a look around the forums- you're bound to find something you'd love.

Anyways, if you find any glitches or bugs in any of these scripts, please tell me, and I will try to fix them as soon as I can. Good luck with finishing that map!
Title: Re: Remote shield emitter
Post by: Dook on July 13, 2014, 08:23:41 AM
ah very nice. looks like what i had in mind. i'll get a crakin on the map
Title: Re: Remote shield emitter
Post by: Dook on July 13, 2014, 10:04:21 AM
The mortars work as described. I see you are pointing me in the direction towards turning them off for phase one (prior to batterys being destroyed). I added SetScriptVar("spawnedEmitterProductionAmt" 0) under "once" in the AntiUnitShieldBattery script in hopes that once all batterys are destroyed the spawned emitter production amount reverts back to the set value in the placed CRPL core. not sure if it works that way though. And regardless i failed at even turning them off  :'( .
Title: Re: Remote shield emitter
Post by: ParkourPenguin on July 13, 2014, 11:21:30 AM
Well, according to the SetScriptVar wiki page (http://knucklecracker.com/wiki/doku.php?id=crpl:docs:setscriptvar), SetScriptVar takes 4 arguments to work: Unit UID, script name, var name, and var value.

Unit UID is simply a unique integer assigned to each unit. I do not believe there is any way for two units to have the same UID on the same map. You can get this value by using GetUnitAt (http://knucklecracker.com/wiki/doku.php?id=crpl:docs:getunitat). GetUnitAt is fairly simple- give it an X-Coordinate and a Y-Coordinate, and it will give you the UID of whatever unit may be there.

Script name should be fairly straightforward- it's the name of the script that contains the value you want to modify. In this case, it should be "CreeperMortar.crpl".

Var name is also straightforward- it's the name of the variable you want to modify. This should be "spawnedEmitterProductionAmt".

Var value is what you want the variable to be. In the case of where you want to disable spawning emitters, this should be 0. If you do want them to spawn emitters, however, then this should be something greater than 0.

As an example, let's say a CRPL tower with CreeperMortar.crpl attached to it is at X,Y. This is roughly what you should do to set the variable:
GetUnitAt(<-X <-Y) ->mortarUID
SetScriptVar(<-mortarUID "CreeperMortar.crpl" "spawnedEmitterProductionAmt" 0)


However, as stated previously, this will prevent mortars from spawning in emitters.

But, if you want the mortars to spawn emitters when all of the batteries are destroyed, there may be an easier way to do this. Instead of checking whether or not all the batteries are destroyed, you can check if the shield is down from the mortars themselves via GetScriptVar (http://knucklecracker.com/wiki/doku.php?id=crpl:docs:getscriptvar) (works very similar to how SetScriptVar works, only excludes var value), and if so, allow emitters to be spawned in. You'll have to get the UID of the shield you want to check, of course. Again, assume the shield is at X,Y:
GetUnitAt(<-X <-Y) ->shieldUID
if(GetScriptVar(<-shieldUID "AntiUnitShield.crpl" "isShieldActive") not)  # if the shield is not active, then spawn
    20 ->spawnedEmitterProductionAmt                                      # in emitters that produce 20 creeper.
endif


GetUnitAt(<-X <-Y) ->shieldUID would best be placed somewhere in the once...endonce block of CreeperMortar.crpl. Try right before endonce. Just note that you'll have to manually input the coordinates of the shield you want to check.
You'll have to put the if statement somewhere in CreeperMortar.crpl where it will loop. Try right before :fireMortar and after endif.

Here is what the final thing should look like, with a shield located at X = 125, Y = 50:
Spoiler
# CreeperMortar.crpl
# Created by: ParkourPenguin
# Created on: 7/9/2014
# Last edited: 7/13/2014
# ------------------------------------------
$mortarInterval:450
$mortarPayload:100.0
$mortarTargetX:0
$mortarTargetY:0
$mortarTargetRadius:10.0
$spawnedEmitterProductionAmt:0.0
$spawnedEmitterProductionInterval:15
$projectileImage:"Custom0"
$projectileSpeed:1.5
$projectileAngularVelocity:1.0
$projectileUpdateDelay:0
$triggerRange:0.0
$emitInterval:15
$emitAmount:20.0

once
   self CONST_COUNTSFORVICTORY true SetUnitAttribute
   self CONST_NULLIFIERDAMAGES true SetUnitAttribute
   
   "mortarInterval" @makePos
   "mortarTargetX" @makePos
   "mortarTargetY" @makePos
   "mortarTargetRadius" @makePos
   "spawnedEmitterProductionInterval" @makePos
   "projectileSpeed" @makePos
   "projectileUpdateDelay" @makePos
   "triggerRange" @makePos
   "emitInterval" @makePos
   
   if(<-mortarTargetX MapWidth gte)
      MapWidth 1 sub ->mortarTargetX
   endif
   
   if(<-mortarTargetY MapHeight gte)
      MapHeight 1 sub ->mortarTargetY
   endif

   GetUnitAt(125 50) ->shieldUID

endonce

if(CurrentCoords <-triggerRange GetUnitCountInRange eq0 <-projectileSpeed neq0 and)
   @fireMortar
   <-mortarInterval Delay
else
   @produceCreeper
   <-emitAmmount Delay
endif

if(GetScriptVar(<-shieldUID "AntiUnitShield.crpl" "isShieldActive") not)
    20 ->spawnedEmitterProductionAmt
endif

:fireMortar
RandFloat pi 2 mul mul ->angle
RandFloat <-mortarTargetRadius mul ->dist
<-angle cos <-dist mul floor <-mortarTargetX add ->tX
<-angle sin <-dist mul floor <-mortarTargetY add ->tY
if(<-tX MapWidth gte)
   MapWidth 1 sub 2 mul <-tX sub ->tX
endif
if(<-tY MapHeight gte)
   MapHeight 1 sub 2 mul <-tY sub ->tY
endif

"CRPLCORE" CurrentCoords CreateUnit ->shellID
<-shellID "MortarShell.crpl" AddScriptToUnit
<-shellID "main" <-projectileImage SetImage
<-shellID "MortarShell.crpl" "targetX" <-tX abs SetScriptVar
<-shellID "MortarShell.crpl" "targetY" <-tY abs SetScriptVar
<-shellID "MortarShell.crpl" "payload" <-mortarPayload SetScriptVar
<-shellID "MortarShell.crpl" "emitterProductionAmt" <-spawnedEmitterProductionAmt SetScriptVar
<-shellID "MortarShell.crpl" "emitterProductionInterval" <-spawnedEmitterProductionInterval SetScriptVar
<-shellID "MortarShell.crpl" "speed" <-projectileSpeed SetScriptVar
<-shellID "MortarShell.crpl" "angularVelocity" <-projectileAngularVelocity SetScriptVar
<-shellID "MortarShell.crpl" "updateDelay" <-projectileUpdateDelay SetScriptVar

:produceCreeper
CurrentCoords <-emitAmmount
if(CurrentCoords GetCreeper 0 gt)
    SetCreeper
else
   AddCreeper
endif

:makePos
dup
<-! 0 lt if
   dup <-! neg swap ->!
else
   pop
endif
[close]

If you would like any more help with trying to figure out how to do something, don't hesitate to ask!
Title: Re: Remote shield emitter
Post by: Dook on July 13, 2014, 12:21:21 PM
You have been very helpful. thank you. i'll have to also set the projectile speed to zero to prevent it from firing and revert it to producing creeper only during phase 1. which should just be as simple as entering 1.5 ->projectileSpeed under the if statement. with this method i can also increase its emitter amount when triggered by a player coming in range during phase 2. very cool.
Title: Re: Remote shield emitter
Post by: Dook on July 15, 2014, 01:08:38 AM
I got the mortars to function in a 2 phase manner. although i'm not sure if i'm not getting the variables or its a bug but i'm having an issue getting the mortar to spawn creeper (non-projectile). I have spawnedEmitterProductionAmt set to zero and projectileSpeed set to zero yet they do not produce any creeper. i've tried triggerrange zero and 10. neither works. and it persists to phase 2 when the the variables are spawnedEmitterProductionAmt 20 and projectileSpeed 1.5

this is what i inserted to the script
if(GetScriptVar(<-shieldUID "AntiUnitShield.crpl" "isShieldActive") not)
    20 ->spawnedEmitterProductionAmt
1.5 ->projectileSpeed
else
0 ->spawnedEmitterProductionAmt
0 ->projectileSpeed
endif


not sure if i messed something up with the original script


Also would it be possible to have the mortar play a sound and play an effect when it launches projectiles. not a projectile effect as thats taken care of already with customimages. but just an effect centered on the mortar during launch. i've looked at the mortar script on edurans map that accomplishes this but my head was about to explode trying to intergrate it into your script.
Title: Re: Remote shield emitter
Post by: Relli on July 15, 2014, 08:55:59 AM
Without seeing the whole code, all I can say is check two variables, emitAmount and emitInterval. If either of those were 0, for instance, the Mortar wouldn't be able to toss out creeper.
Title: Re: Remote shield emitter
Post by: Dook on July 15, 2014, 09:06:55 AM
both are set. emitInterval set at 15, emitAmount set at 20.
Title: Re: Remote shield emitter
Post by: ParkourPenguin on July 15, 2014, 03:03:21 PM
That was a bug you were experiencing. A typo, more specifically. My bad.  :-[

For the sound and visual effects, it's easier than you think. From looking at my script, the function :fireMortar is where it creates the projectile and assigns it all the variables it needs. So, if you want to play a sound and create an effect whenever it fires, just use the PlaySound and CreateEffect commands in that function. Like so:

"Weapons24" PlaySound
3 CurrentPixelCoords -1 1.0 1.0 1.0 30.0 div CreateEffect


For PlaySound, you can get all the names of the sounds and even sample them by clicking on "Sounds" in the unit menu when in the world editor. Check out the wiki page by clicking here (http://knucklecracker.com/wiki/doku.php?id=crpl:docs:playsound) for more information.


For CreateEffect, it gets a little more complicated:
Check out the wiki by clicking here (http://knucklecracker.com/wiki/doku.php?id=crpl:docs:createeffect) for more information on CreateEffect.

I updated the code below with the typo fix and those two lines of code (they're at the end of :fireMortar). By the way, one small thing I did was move your if statement that checks if the shield is down above the other if statement. It shouldn't make that much of a difference, but I did think of something minor that could happen if it wasn't above it.
Spoiler
# CreeperMortar.crpl
# Created by: ParkourPenguin
# Created on: 7/9/2014
# Last edited: 7/15/2014
# ------------------------------------------
$mortarInterval:450
$mortarPayload:100.0
$mortarTargetX:0
$mortarTargetY:0
$mortarTargetRadius:10.0
$spawnedEmitterProductionAmt:0.0
$spawnedEmitterProductionInterval:15
$projectileImage:"Custom0"
$projectileSpeed:1.5
$projectileAngularVelocity:1.0
$projectileUpdateDelay:0
$triggerRange:0.0
$emitInterval:15
$emitAmount:20.0

once
   self CONST_COUNTSFORVICTORY true SetUnitAttribute
   self CONST_NULLIFIERDAMAGES true SetUnitAttribute
   
   "mortarInterval" @makePos
   "mortarTargetX" @makePos
   "mortarTargetY" @makePos
   "mortarTargetRadius" @makePos
   "spawnedEmitterProductionInterval" @makePos
   "projectileSpeed" @makePos
   "projectileUpdateDelay" @makePos
   "triggerRange" @makePos
   "emitInterval" @makePos
   
   if(<-mortarTargetX MapWidth gte)
      MapWidth 1 sub ->mortarTargetX
   endif
   
   if(<-mortarTargetY MapHeight gte)
      MapHeight 1 sub ->mortarTargetY
   endif
   
endonce

if(GetScriptVar(<-shieldUID "AntiUnitShield.crpl" "isShieldActive") not)
   20 ->spawnedEmitterProductionAmt
   1.5 ->projectileSpeed
else
   0 ->spawnedEmitterProductionAmt
   0 ->projectileSpeed
endif

if(CurrentCoords <-triggerRange GetUnitCountInRange eq0 <-projectileSpeed neq0 and)
   @fireMortar
   <-mortarInterval Delay
else
   @produceCreeper
   <-emitInterval Delay
endif


:fireMortar
RandFloat pi 2 mul mul ->angle
RandFloat <-mortarTargetRadius mul ->dist
<-angle cos <-dist mul floor <-mortarTargetX add ->tX
<-angle sin <-dist mul floor <-mortarTargetY add ->tY
if(<-tX MapWidth gte)
   MapWidth 1 sub 2 mul <-tX sub ->tX
endif
if(<-tY MapHeight gte)
   MapHeight 1 sub 2 mul <-tY sub ->tY
endif

"CRPLCORE" CurrentCoords CreateUnit ->shellID
<-shellID "MortarShell.crpl" AddScriptToUnit
<-shellID "main" <-projectileImage SetImage
<-shellID "MortarShell.crpl" "targetX" <-tX abs SetScriptVar
<-shellID "MortarShell.crpl" "targetY" <-tY abs SetScriptVar
<-shellID "MortarShell.crpl" "payload" <-mortarPayload SetScriptVar
<-shellID "MortarShell.crpl" "emitterProductionAmt" <-spawnedEmitterProductionAmt SetScriptVar
<-shellID "MortarShell.crpl" "emitterProductionInterval" <-spawnedEmitterProductionInterval SetScriptVar
<-shellID "MortarShell.crpl" "speed" <-projectileSpeed SetScriptVar
<-shellID "MortarShell.crpl" "angularVelocity" <-projectileAngularVelocity SetScriptVar
<-shellID "MortarShell.crpl" "updateDelay" <-projectileUpdateDelay SetScriptVar

"Weapons24" PlaySound
1 CurrentPixelCoords 1 1.0 1.0 1.0 30.0 div CreateEffect

:produceCreeper
CurrentCoords <-emitAmount
if(CurrentCoords GetCreeper 0 gt)
   SetCreeper
else
   AddCreeper
endif

:makePos
dup
<-! 0 lt if
   dup <-! neg swap ->!
else
   pop
endif
[close]
Title: Re: Remote shield emitter
Post by: Dook on July 16, 2014, 01:21:00 PM
Well its nearly finished. just a few more trial runs threw the map. heres a progress screen shot.
(http://i.imgur.com/edtG1fR.jpg)

unfortunately (or fortunately?) i've noticed a bug on my last trial run. For some reason the shield deactivates itself during the course of a game. even if its getting ammo.
i've included the map .cw3 and the save where it no longer works if that helps pin point it.
Title: Re: Remote shield emitter
Post by: ParkourPenguin on July 16, 2014, 09:04:48 PM
Unfortunately, the bug did not persist across the save. The saves were still helpful, however.

The only way the shield could deactivate is if either it's destroyed (probably not the case), or the current ammo is 0, max ammo is greater than 0, and the shield is currently active. The last two can reasonably be assumed to always be true, so the ammo must be 0, which means that the batteries probably aren't giving the tower any ammo, even if the effects made by the batteries make it seem like they are.

I noticed that in your map you had an inhibitor right beneath the unit shield. This might be messing with the GetUnitAt command, as it may get the UID of the inhibitor as opposed to the shield. As such, I've come up with a different method of getting the UID of the shield. It's a bit more complicated, but getting the incorrect UID of a unit at the same place as the shield shouldn't be a problem anymore.

I modified AntiUnitShieldBattery.crpl and I made a very slight modification to AntiUnitShield.crpl just to make sure that it would work. I ripped both scripts from DN007.cw3 and modified those, so you should be able to simply plug them right back in and not worry about any modifications you made to those scripts being messed up. Both are attached below.

If you come across this bug again, please tell me if the ammo bar above the shield is showing anything, as this will let me know if the current ammo is 0. I hope this helps!
Title: Re: Remote shield emitter
Post by: Dook on July 17, 2014, 12:50:48 AM
Ah ya i should of seen sticking multiple units in the same location would cause a conflict. thanks for updating the script. Although i've got the bug to happen again. Think i narrowed it down this time. modified the map so there are no units besides the anti unit shield core at the center to remove possibilitys. The bug seems to appear on loading from a saved game. Recompiling the scripts fixes it but a player wont be able to do that.
Title: Re: Remote shield emitter
Post by: ParkourPenguin on July 17, 2014, 10:55:05 AM
Quote from: Dook on July 17, 2014, 12:50:48 AM
Ah ya i should of seen sticking multiple units in the same location would cause a conflict. thanks for updating the script. Although i've got the bug to happen again. Think i narrowed it down this time. modified the map so there are no units besides the anti unit shield core at the center to remove possibilitys. The bug seems to appear on loading from a saved game. Recompiling the scripts fixes it but a player wont be able to do that.

Ah... ok. That's very helpful- I'll see if I can't pinpoint it; however, I need to do something today, so the earliest I'll be able to have the script updated is probably in another 7-10 hours or so. But if someone else wants to take a look at the script and try to solve the bug sooner, feel free to!
Title: Re: Remote shield emitter
Post by: Grayzzur on July 17, 2014, 12:46:04 PM
A save game made prior to the script updates would still have the old scripts embedded in it, and thus would still have the bug.
Title: Re: Remote shield emitter
Post by: Dook on July 17, 2014, 01:22:21 PM
Rechecked the scripts and recompiled. The bug is actually easily reproduced. start a game, save, reload that save and the shields are down. I also noticed that on map start before the game is unpaused you can freely build in the shield area. as soon as the map is unpaused the shield activates but any structures there remain. When using the reload method the same thing happens but the shield remains down. I figured the map start thing was because the scripts haven't initialized yet so i modified the terrain in the central area to prevent building. But it would be an issue if it happens on every reload as a player can terp the terrain, save, then reload and build a nullifier -> win.


I've attached the current map in case that helps with the south west corner of the shielded area having clear terrain for testing. And i'm thankful for any work that do on this. take your time.
Title: Re: Remote shield emitter
Post by: Relli on July 17, 2014, 01:37:54 PM
I feel like both of those problems could be solved by putting the creation of the shield inside an :Awake. It should load up even before you unpause for the first time, and every time you reload the game as well. That said, I've never really used Awake, so there's a chance it doesn't work like that. But you should try it to be sure.
Title: Re: Remote shield emitter
Post by: Grayzzur on July 17, 2014, 03:46:52 PM
Depending on the behavior you're after, :Awake and :GameLoaded should be looked into for that. Virgil posted the difference in another thread here (http://knucklecracker.com/forums/index.php?topic=15379.msg112626#msg112626).
Title: Re: Remote shield emitter
Post by: ParkourPenguin on July 17, 2014, 04:30:20 PM
A big thank you to Relli and Grayzzur! I found out what was causing that bug.

When the map saves, it doesn't save any changes caused by SetCellOccupiedCount; however, it still saves the boolean that says whether or not the shield is up. As such, when you load a saved game, the anti unit shield core will still think that the shield is up, when it actually isn't because it wasn't saved.

To try to fix this, I added an :Awake function that's called when the core is created. It should create a shield if the boolean says that there was a shield up previously, the current ammo is greater than 0, or the user-defined variable maxAmmo is less than 0 (which means you want the shield to always be up, regardless of whether or not it's being fed ammo). You can insert the following code right above :destroyed, and it should work out just fine:
:Awake
if(<-isShieldActive self CONST_AMMO GetUnitAttribute 0 gt or <-maxAmmo 0 lt or)
@activateShield
endif


When updating the scripts, a glitch can happen where the shield will persist even after it's destroyed. To prevent this, after you recompile the scripts with this fix, immediately save and load the map, and you should be fine.
Title: Re: Remote shield emitter
Post by: Dook on July 18, 2014, 06:06:01 AM
Yup that seemed to fix it perfectly. tested it a good bit and couldn't find any more bugs. decided to upload it, map #866 , thank you for all your work. i enjoyed playing against the scripts. already getting ideas for putting the creeper mortar in more of the spot light on the next map. the original non-emitter spitting version. thanks again.