Platypus Reclayed : Version 1.4.0 released!
Version 1.4.0 released!
Version 1.4.0 has landed!
This update focuses on a whole host of new modding features and some fixes sprinkled in too.
New Level commands
• Added `waitForNoSpecificEntity(string entity, int timeout = -1)`
• Added `ifNotSpecificEntityOnScreen(string entity, int places)`
• Added `ifCreditCountBelow(int creditCount, int places)`
• Added `ifCreditCountAbove(int creditCount, int places)`
• Added `ifCreditCountEqual(int creditCount, int places)`
• Added `ifPlayerWeaponIs(int weaponID, int places)`
• Added `ifPlayerHasPods(int places)`
• Added `destroyEntityOfType(string entityName, bool isKill)`
• Added `destroyEntitiesOfType(string entityName, bool isKill)`
• Added [c]destroyEnemyEntities(bool isKill)[/c]
Audio Definitions
• Added `s_pause`: this is a duplicate of `s_star1`
• Added `s_exit_attract`: this is a duplicate of `s_star1`
• Added `s_ui_main_toggle_sfx_setting`: this is a duplicate of `s_star1`
• Added optional `s_fruit_cherry`: if not defined, we simply fall back to `s_fruit` (pickup sfx)
• Added optional `s_fruit_cherry_small`: if not defined, we simply fall back to `s_fruit` (pickup sfx)
• Added optional `s_fruit_bananas`: if not defined, we simply fall back to `s_fruit` (pickup sfx)
• Added optional `s_fruit_bananas_small`: if not defined, we simply fall back to `s_fruit` (pickup sfx)
• Added optional `s_fruit_grapes`: if not defined, we simply fall back to `s_fruit` (pickup sfx)
• Added optional `s_fruit_grapes_small`: if not defined, we simply fall back to `s_fruit` (pickup sfx)
• Added optional `s_fruit_coin`: if not defined, we simply fall back to `s_fruit[c] (pickup sfx[/c]
Lua API
• Piped lua’s default print function to the game’s log
• Made use of JSONObject fallbacks in `saucer.lua`’s commandArgs
• Changed `SpawnEntityWorld(entityName, worldPosition, arguments)`: Now returns an integer, this is the entityID
• Changed `SpawnEntityWorld(entityName, worldPosition, arguments)`: Argument parameter is now optional (no longer requiring creation of an empty JSONObject)
• Changed `SpawnEntityLocal(entityName, localPosition, arguments)`: Now returns an integer, this is the entityID
• Changed `SpawnEntityLocal(entityName, localPosition, arguments)`: Argument parameter is now optional (no longer requiring creation of an empty JSONObject)
• Changed `SpawnEntityChild(entityName, parent, positionOffset, arguments)`: Now returns an integer, this is the entityID
• Changed `SpawnEntityChild(entityName, parent, positionOffset, arguments)`: Argument parameter is now optional (no longer requiring creation of an empty JSONObject)
• Added `GetEntity(entityID)`
• Changed `GetPlayer(index)`: Now expects an integer
• Added `MoveTowardsAngle(current, target, maxDelta)`
• Added `DeltaAngle(current, target)`
• Added `IsOriginalVersion()`
• Added `GetSpriteDimensions(animationName, spriteIndex)`
• Added `MakeBonuses(x, y, fruitSetID)`
• Added `AdjustXToWideScreen(x)`
• Added `NewDiffDictInt(veryEasy, easy, normal, hard, nasty)`
• Added `NewDiffDictFloat(veryEasy, easy, normal, hard, nasty)`
• Added `NewDiffDictBool(veryEasy, easy, normal, hard, nasty)`
• Added `NewDiffDictString(veryEasy, easy, normal, hard, nasty)`
• Added `NewDiffDictIntArray(veryEasy, easy, normal, hard, nasty)`
• Added `NewDiffDictFloatArray(veryEasy, easy, normal, hard, nasty)`
• Added `NewDiffDictBoolArray(veryEasy, easy, normal, hard, nasty)`
• Added `NewDiffDictStringArray(veryEasy, easy, normal, hard, nasty)`
• Added `Globals.isPassiveResistance`
• Added `Globals.trainEntities`
• Added `Globals.trainBonus`
• Added `Globals.trainCounter`
• Added `Globals.custom`
• Fixed `Globals.ScrollingSpeed(layer)` being nil
• Fixed `Globals.firewait` being nil
• Fixed `Globals.levelLifetime` being nil
• Fixed `Globals.createSplashes` being nil
• Fixed `Globals.bonusScores` being nil
• Fixed `Globals.layerScaleValues` being nil
• Fixed `Globals.horizonLevels` being nil
• Fixed `Globals.layerReflections` being nil
• Fixed `Globals.firingChanceSaucer` being nil
• Fixed `Globals.firingChanceRandomFishFighter` being nil
• Added `SpriteAnimator.worldPosition`
• Added `SpriteAnimator.rotation`
• Added `SpriteAnimator.enabled`
• Added `Player.lastUpdateTime`
• Added `Player.nextUpdateTime`
• Added `Player.lastPosition`
• Added `Player.nextPosition`
• Added `Player.position`
• Added `Player.worldPosition`
• Added `Player.isActive`
• Deprecated `Player.GetPosition()`: use `Player.position` instead
• Deprecated `Player.GetWorldPosition()`: use `Player.worldPosition` instead
• Added `BaseEntity.customBehaviourData`
• Added `BaseEntity.entityID`
• Added `BaseEntity.lastUpdateTime`
• Added `BaseEntity.nextUpdateTime`
• Added `BaseEntity.lastPosition`
• Added `BaseEntity.nextPosition`
• Added `BaseEntity.rotation`
• Added `BaseEntity.defaultOnHitByBulletBehaviour`
• Added `BaseEntity.defaultOnHitByPlayerBehaviour`
• Added `BaseEntity.BulletConsume(consumer)`
• Added `BaseEntity.BulletGetKillCreditIndex()`
• Added `BaseEntity.EndKillTimer()`
• Fixed `BaseEntity.GetDamageFrame(maxHitPoints, hitPoints, frameCount)` being nil
• Fixed `BaseEntity.CheckCollision(collider, playerCollisionCallback?, bulletCollisionCallback?)` behaving incorrectly when passing nil as callbacks
• Fixed `BaseEntity.SpawnShipDebris(count, mxMin, mxMax, myMin, myMax, xOffset, yOffset, mxSpawnDirectionMin, mxSpawnDirectionMax, mySpawnDirectionMin, mySpawnDirectionMax)` not spawning secondary debris
• Changed `JSONObject.GetFieldString(name)`: To take an additional `fallback?` parameter: e.g. `GetFieldString(my_name, my_fallback_value)`
• Changed `JSONObject.GetFieldFloat(name)`: To take an additional `fallback?` parameter: e.g. `GetFieldFloat(my_name, my_fallback_value)`
• Changed `JSONObject.GetFieldInt(name)`: To take an additional `fallback?` parameter: e.g. `GetFieldInt(my_name, my_fallback_value)`
• Changed `JSONObject.GetFieldBool(name)`: To take an additional `fallback?` parameter: e.g. `GetFieldBool(my_name, my_fallback_value)`
• Changed `JSONObject.GetFieldStringArray(name)`: To take an additional `fallback?` parameter: e.g. `GetFieldStringArray(my_name, my_fallback_value)`
• Changed `JSONObject.GetFieldFloatArray(name)`: To take an additional `fallback?` parameter: e.g. `GetFieldFloatArray(my_name, my_fallback_value)`
• Changed `JSONObject.GetFieldIntArray(name)`: To take an additional `fallback?` parameter: e.g. `GetFieldIntArray(my_name, my_fallback_value)`
• Changed `JSONObject.GetFieldBoolArray(name)`: To take an additional `fallback?` parameter: e.g. `GetFieldBoolArray(my_name, my_fallback_value)`
• Removed `FirePattern.NewFirePatternFromEntityData(data)`: It was nil before, so no compatibility breaks
• Added `TurretData.CalculateBulletParams(worldPosition, angleOffset)`
• Added `Collider2D.boolean`
• Added `Collider2D.SetLogicLayerDefault()`
• Added `Collider2D.SetLogicLayerTransparentFX()`
• Added `Collider2D.SetLogicLayerIgnoreRaycast()`
• Added `Collider2D.SetLogicLayerWater()`
• Added `Collider2D.SetLogicLayerUI()`
• Added `Collider2D.SetLogicLayerPlayer()`
• Added `Collider2D.SetLogicLayerPlayerShot()`
• Added `Collider2D.SetLogicLayerEnemy()`
• Added `Collider2D.SetLogicLayerEnemyShot()`
• Added `Collider2D.SetLogicLayerLoadScreen()`
• Added `Collider2D.SetLogicLayerPlayerPickupCollider()`
• Added `Collider2D.SetLogicLayerPickup()`
• Added [c]Collider2D.SetLogicLayerPlayerShotNoFruit()[/c]
Lua globals.lua
• Defined `AnimationType`: Enum for usable values (previously only in the documentation)
• Defined `GameDifficulty`: Enum for usable values (previously only in the documentation)
• Defined `ScoreSource`: Enum for usable values (previously only in the documentation)
• Added `RandRangeF(min, max)`
• Added `RandRange(min, max)`
• Added `Round(value)`
• Added `Clamp(value, min, max)`
• Added `Lerp(min, max, t)`
• Added `CreateTurret(entity, xOff, yOff, parent, waiter)`
• Deprecated `round(value)`: Use `Round(value)` instead
• Deprecated `clamp(value, min, max)`: Use `Clamp([c]alue, min, max` instea[/c]
Example scripts
• Implemented `car.lua` example scriptThis is the stage one boss in the gameExample of turret entities, in this case spawning them manuallyExample of Global countersExample of multi entity enemiesExample of a boss fightExample of custom hit responses using custom collidersExample of linked enemies (movement depending on the next segment)Example of `BaseEntity.IsKilledManually`Example of spawning other entitiesExample of `EntityData.customBehaviourData`
• Implemented `enemy_bullet.lua` example scriptThis is the basic bullets fired by saucers and other enemiesExample of `EntityData.customBehaviourData`Example of manual sprite frame handlingExample of player dependent logic
• Implemented `reclayed_turret.lua` example scriptThis is the base for most of the turrets usedExample of TurretDataExample of FirePatternExample of stationary enemy, designed to be attached to anotherExample of properly spawning bulletsExample of `EntityData.customBehaviourData`Example of player dependent logic
Misc
• Fixed Boss 1 sometimes not sorting correctly, this was visible on the chain element
• Fixed `EnemyHomerBullet` corrupting when multiple entities used it with differing `customBehaviourData`
• Exposed `speed` and `tickTurnDegrees` as `customBehaviourData` in `HomingMissile` behaviour
• Increased class strictness in LLS definition `types.lua` (Will now warn you if you try to use a field that doesn’t exist)
• Added `Trail` behaviour, functioning as a way to create customizable trails for any entity. See ` »exampleTrail »` in `entities.json`
• Fixed `Lua` behaviours not defaulting to the default layer when reused
• Fixed `Lua` cleaning up their functions too early (the game expects function pointers to still be valid during the frame kill was called)
• Updated documentation
