Remote shield emitter

Started by Dook, July 10, 2014, 09:55:05 AM

Previous topic - Next topic

Dook

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.

Relli

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.

Dook

both are set. emitInterval set at 15, emitAmount set at 20.

ParkourPenguin

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 for more information.


For CreateEffect, it gets a little more complicated:

  • The first number you see is an integer that identifies which effect should be played.
  • The next two numbers identify the pixel coordinates where the effect should be played.
  • The next one, -1, is the z-coordinate which identifies what things are displayed on top. Set this to -1 for the effect to be played over the tower or set this to 1 for it to be shown below the tower.
  • The next two numbers are the scale of the image, or how big it is (the reason why I added the .0 at the end of these is because the compiler should interpret this as a float instead of an integer).
  • And that last number, 1/30, is the speed at which it should be played. 1/30 is normal. If you change this, make sure you have a decimal at the end even if it's .0, or else the compiler will treat it as an integer and truncate it to 0.
Check out the wiki by clicking here 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]
"Only a life lived for others is a life worthwhile."
-Albert Einstein

Dook

Well its nearly finished. just a few more trial runs threw the map. heres a progress screen shot.


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.

ParkourPenguin

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!
"Only a life lived for others is a life worthwhile."
-Albert Einstein

Dook

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.

ParkourPenguin

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!
"Only a life lived for others is a life worthwhile."
-Albert Einstein

Grayzzur

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.
"Fate. It protects fools, little children, and ships named 'Enterprise.'" -William T. Riker

Dook

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.

Relli

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.

Grayzzur

Depending on the behavior you're after, :Awake and :GameLoaded should be looked into for that. Virgil posted the difference in another thread here.
"Fate. It protects fools, little children, and ships named 'Enterprise.'" -William T. Riker

ParkourPenguin

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.
"Only a life lived for others is a life worthwhile."
-Albert Einstein

Dook

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.