Fix all links, lists and tables rendering
This commit is contained in:
@@ -26,7 +26,7 @@ This means it will NEVER contain any of the following:
|
||||
|
||||
This isn't just for obvious legal reasons (mainly the code part), but also because these aren't actually helpful here. There are many reasons:
|
||||
|
||||
- For code, It can leavy the wrong impression without understanding the proper context of how the game was made. This is because there are parts of the code that suffers from tight coupling or have a monolithic approach which can lead to developmental issues which affects modding. This context explains everything, but is easily overlooked and it isn't really necessary to mention to document the internals unless it becomes historically relevant (such as described a known issue with how it happened). Avoiding to share code avoids this perception problem.
|
||||
- For code, It can leave the wrong impression without understanding the proper context of how the game was made. This is because there are parts of the code that suffers from tight coupling or have a monolithic approach which can lead to developmental issues which affects modding. This context explains everything, but is easily overlooked and it isn't really necessary to mention to document the internals unless it becomes historically relevant (such as described a known issue with how it happened). Avoiding to share code avoids this perception problem.
|
||||
- For data files, it's simply because there's no point: the formats are not made to be human readable because automated tools generated them. The goal of this repos is to allow them to be readable by external tools or by a human manually. As for why not providing aggregated versions of them, it's because they arguably don't belong in a docs repos which should only contain the specification of the data, but not its implementation. I rather decouple the 2 since the data won't change, but the knowledge of it can.
|
||||
- For Unity assets, it's just because the actual instances (mainly the maps prefabs) don't matter as much for this repos. What matters is how they work so one can pick an actual instance and understand what it is telling the game to do.
|
||||
- For anything else, it's not needed + the less files I share from the game, the better.
|
||||
@@ -14,7 +14,7 @@ The actual clip that will be played can change under specific conditions. They a
|
||||
* if `inice` or `hasiceanim`, the `i` argument is appended to `args`
|
||||
* The `u` argument is removed from `args` if `force` is true (NOTE: this argument is not used in the game so this effectively does nothing)
|
||||
* If the new [animstate](animstate.md) is 30 (`FakeHurt`), it is overriden to 11 (`Hurt`).
|
||||
* On top of this, if `flyinganim`, the `f` argument is prepanded to `args` if it didn't had it already.
|
||||
* On top of this, if `flyinganim`, the `f` argument is prepanded to `args` if it didn't had it already.
|
||||
|
||||
This method is called at specific places (but notably in the entity's LateUpdate) whenever an [animstate](animstate.md) update is required. In which case, this set the entity's `laststate` and it will ask Unity to change the animation clips using CrossFadeInFixedTime at the new clip's name with the time being the entity's `animspeed`. After, [UpdateAnimSpecific](AnimSpecific.md#updateanimspecific) is called.
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
An item entity is an entity that has its `item` field set to true. It completely changes the rendering and updates of that entity.
|
||||
|
||||
The summary as far as the fields are concerned:
|
||||
|
||||
- `item` is true
|
||||
- `animid` is the item type, not an [animid](../../Enums%20and%20IDs/AnimIDs.md)
|
||||
- `animstate` and `itemstate` are both the item id, the former is not an [animstate](Animations/animstate.md) and the latter is assigned on [Start](Start.md) and is used in [UpdateItem](Update%20process/UpdateItem.md)
|
||||
@@ -10,6 +11,7 @@ Additionally, [UpdateItem](Update%20process/UpdateItem.md) is now part of the up
|
||||
|
||||
## Item types
|
||||
The following is the values `animid` can have when we are dealing with an `item` entity. The value also dictates what `animstate` and `itemstate` mean.
|
||||
|
||||
|Value|`itemstate` meaning|Description|
|
||||
|----:|------------------|----------|
|
||||
|0|An [item](../../Enums%20and%20IDs/Items.md) id|Standard item|
|
||||
|
||||
@@ -9,18 +9,18 @@ Here are all the modifiers that are known:
|
||||
|TIME|Sets `extratimer` to true on [Start](Start.md) which doubles the time before the forcemove failsafe triggers|
|
||||
|COT|Sets `hologram` and `cotunknown` to true which makes the entity rendered as a hologram in silhouette. This also calls RefreshCOT in 0.1 seconds which will set the materials of the extras accordingly to cot while setting `refreshedcotu` to true|
|
||||
|ShwKEY|Sets `showitem` to true on [Start](Start.md) if the entity has an `npcdata` which renders a key item on top of the entity (defined in npcdata's data)|
|
||||
|ICE|Sets the npcdata's `extrafreeze` to true on [Start](Start.md) if the entity has an npcdata TODO: Involves [NPCControl](../NPCControl/NPCControl.md)|
|
||||
|ICE|Sets the npcdata's `extrafreeze` to true on [Start](Start.md) if the entity has an npcdata|
|
||||
|Fixed|Sets `fixedentity` to true on [Start](Start.md) and calls SetFixed in 0.1 seconds which will completely lockup the rigid (including disabling gravity, making it kinematic and resetting the velocity to zero), disable the ccol and force the position to be startpos|
|
||||
|FxdCol|A lighter version of Fixed which does everything it does except without disabling the ccol so it stays enabled|
|
||||
|ALW|Sets `alwaysactive` to true on [Start](Start.md) which forces `incamera` to true and the entity remains active even out of the camera's range|
|
||||
|ALF|Sets `alwaysflip` to true on [Start](Start.md) which calls [UpdateFlip](Update%20process/UpdateFlip.md) every LateUpdate|
|
||||
|PAU|Sets `activeonpause` to true on [Start](Start.md) which allows the entity to receive updates and late updates on pause, minipause, [message](../../SetText/Notable%20states.md#message) lock and being dead|
|
||||
|HIDE|Sets `hideinside` to true on [Start](Start.md) TODO: Involves [NPCControl](../NPCControl/NPCControl.md)|
|
||||
|HIDE|Sets `hideinside` to true on [Start](Start.md)|
|
||||
|ROT|LateAngle is called on [CreateEntities](CreateEntities.md) in 0.25 seconds to set the angle instead of setting it direction. It also sets `lockrotater` to true on [Start](Start.md) which locks the y angle of the rotater.|
|
||||
|ShwEm|Sets `alwaysemoticon` to true on [Start](Start.md) TODO: mostly involves [NPCControl](../NPCControl/NPCControl.md)|
|
||||
|ShwEm|Sets `alwaysemoticon` to true on [Start](Start.md)|
|
||||
|COG|Sets `startpos` to the point a raycast will hit from the transform heading down on [Start](Start.md)|
|
||||
|NGS|Sets `onground` to false which forces the GroundDetector to report the entity being in the air on [Start](Start.md)|
|
||||
|NGF|If this has an `npcdata` of type [Enemy](../NPCControl/Enemy.md) and it is cleared for being enabled on its Start, the [GravityFix](../NPCControl/GravityFix.md) coroutine is called at the end of its Start (this does nothing otherwise)|
|
||||
|NGF|If this has an `npcdata` of type [Enemy](../NPCControl/Enemy.md) and it is cleared for being enabled on its Start, the [GravityFix](../NPCControl/Notable%20methods/GravityFix.md) coroutine is called at the end of its Start (this does nothing otherwise)|
|
||||
|ITHD|Calls npcdata's SetHitInteract with HornDash on [Start](Start.md) if the entity has an npcdata|
|
||||
|ITAH|Calls npcdata's SetHitInteract with AnyHorn on [Start](Start.md) if the entity has an npcdata|
|
||||
|NEAR|When CheckNear is called, the entity is destroyed if it is further away than 30.0 units from the player|
|
||||
|
||||
@@ -8,31 +8,31 @@ Here is what the method does:
|
||||
* Unless `overrideshadow` is true, `hasshadow` becomes true if the AnimIDs is not None (which is -1)
|
||||
* `originalid` is set to the current animid
|
||||
* From here, there are 2 special cases that can change what data is used depending on the animid:
|
||||
* If it's `KeyL`, `KeyR` or `Tablet`, then the following fields gets set and nothing else will get assigned from `endata`:
|
||||
* `nomodel`, `overrideanim`, `overrideanimfunc`, `overridemovesmoke` and `overrridejump` are all true
|
||||
* `minheight` is pulled from `endata`
|
||||
* `startbf` is set to `bobrange`
|
||||
* `startbs` is set to `bobspeed`
|
||||
* The appropriate sprite from `Sprites/Objects/artifacts` from the root of the asset tree is set as the entity's sprite
|
||||
* If it's `Strider`, `overridemovesmoke` is set to true, but the rest goes as it normally would with the `endata` loading
|
||||
* If it's `KeyL`, `KeyR` or `Tablet`, then the following fields gets set and nothing else will get assigned from `endata`:
|
||||
* `nomodel`, `overrideanim`, `overrideanimfunc`, `overridemovesmoke` and `overrridejump` are all true
|
||||
* `minheight` is pulled from `endata`
|
||||
* `startbf` is set to `bobrange`
|
||||
* `startbs` is set to `bobspeed`
|
||||
* The appropriate sprite from `Sprites/Objects/artifacts` from the root of the asset tree is set as the entity's sprite
|
||||
* If it's `Strider`, `overridemovesmoke` is set to true, but the rest goes as it normally would with the `endata` loading
|
||||
* If the AnimID is defined, the data from `endata` is assigned, otherwise only `overrridejump` is set to true
|
||||
* [Special AnimID startup](Special%20AnimID%20startup.md)
|
||||
* The object is setup whenever `endata`'s `Object` is true or it's a `CoilyVine` and we aren't dealing with `KeyL`, `KeyR` or `Tablet`. This is done by setting `notalk` to true, `hasshadow` to false, `startscale` to `endata`'s `startscale` and adding the model of the corresponding AnimID via [AddModel](AddModel.md) that's located in `Prefabs/Objects/` with the offset being `endata`'s `modeloffset`. The `animid` is overridden to -1 (None) unless it's a `SavePoint` or a `FlyTrapPlatform`
|
||||
* If we aren't dealing with `KeyL`, `KeyR` or `Tablet` and the original animid is not -1 (None), then further startup steps are performed:
|
||||
* If the `endata`'s `ismodel` is true and it's not an item
|
||||
* The model of the corresponding AnimID that's located in `Prefabs/Objects/` with the offset being `endata`'s `modeloffset` is added via [AddModel](AddModel.md). The offset is overriden to (0.0, 0.0 - `height`, 0.0) if it's a `TrappedMoth`. The `model`'s angles are set to the `endata`'s `modelscale` TODO: why?
|
||||
* From there, there are 3 special cases:
|
||||
* `JumpingSpider`: Set all child of the model to be rendered with the 3F3F3F color (light gray) fully opaque
|
||||
* `Pitcher` or `PictherSummon`: Setup 2 `extras`, one being the object with the tag `PitcherEnd` and the other being the second child of the `model`. The first `extras` gets the `Untagged` tag. For the second one all child's shadowCastingMode is set to TwoSided and the material set accordingly if `hologram` with half transparency. Finally, `spinextra` is set to to one vector being (0.0, 0.0, -0.2)
|
||||
* `Submarine`: If there's an `npcdata` and it's not the player's entity, the `ccol` is enabled and adjusted to have a radius of 2.5. The `npcdata`'s `colliderheight` is set to 20.0. NOTE: the enabling happens in 0.2 seconds in the future
|
||||
* [UpdateAnimSpecific](../Animations/AnimSpecific.md#updateanimspecific) is called
|
||||
* More `endata` fields are loaded:
|
||||
* `emoticonoffset` to `freezeflipoffset`
|
||||
* `freezesize` (defaults to (2.0, 2.0, 1.0) if this and `freezeoffset` is 0)
|
||||
* `freezeoffset` (defaults to (0.0, 1.0, 0.0) if this and `freezesize` is 0)
|
||||
* `initialfrezeoffset` is set to `freezeoffset`
|
||||
* If there's a `preloaddata` in `endata`, they are all loaded into `preloadedobjects` and `preloadedsprites` by loading the actual prefabs/sprites. They remain null otherwise
|
||||
* If the current map is laoded and we aren't in a battle
|
||||
* if the current map is MetalLake, `startscale` is multiplied by 0.35 and the `emoticon`'s localscale is set to (0.65, 0.65, 0.65)
|
||||
* If the current map's `waterfloat` is present and we are dealing with a `Strider`, `ignorewater` and `alwaysactive` are set to true on top of the ignoring the collider of the map's `waterfloat` with this entity. Finally, the y position of the entity is set to the one of the `waterfloat`
|
||||
* If the `endata`'s `ismodel` is true and it's not an item
|
||||
* The model of the corresponding AnimID that's located in `Prefabs/Objects/` with the offset being `endata`'s `modeloffset` is added via [AddModel](AddModel.md). The offset is overriden to (0.0, 0.0 - `height`, 0.0) if it's a `TrappedMoth`. The `model`'s angles are set to the `endata`'s `modelscale` TODO: why?
|
||||
* From there, there are 3 special cases:
|
||||
* `JumpingSpider`: Set all child of the model to be rendered with the 3F3F3F color (light gray) fully opaque
|
||||
* `Pitcher` or `PictherSummon`: Setup 2 `extras`, one being the object with the tag `PitcherEnd` and the other being the second child of the `model`. The first `extras` gets the `Untagged` tag. For the second one all child's shadowCastingMode is set to TwoSided and the material set accordingly if `hologram` with half transparency. Finally, `spinextra` is set to to one vector being (0.0, 0.0, -0.2)
|
||||
* `Submarine`: If there's an `npcdata` and it's not the player's entity, the `ccol` is enabled and adjusted to have a radius of 2.5. The `npcdata`'s `colliderheight` is set to 20.0. NOTE: the enabling happens in 0.2 seconds in the future
|
||||
* [UpdateAnimSpecific](../Animations/AnimSpecific.md#updateanimspecific) is called
|
||||
* More `endata` fields are loaded:
|
||||
* `emoticonoffset` to `freezeflipoffset`
|
||||
* `freezesize` (defaults to (2.0, 2.0, 1.0) if this and `freezeoffset` is 0)
|
||||
* `freezeoffset` (defaults to (0.0, 1.0, 0.0) if this and `freezesize` is 0)
|
||||
* `initialfrezeoffset` is set to `freezeoffset`
|
||||
* If there's a `preloaddata` in `endata`, they are all loaded into `preloadedobjects` and `preloadedsprites` by loading the actual prefabs/sprites. They remain null otherwise
|
||||
* If the current map is laoded and we aren't in a battle
|
||||
* if the current map is MetalLake, `startscale` is multiplied by 0.35 and the `emoticon`'s localscale is set to (0.65, 0.65, 0.65)
|
||||
* If the current map's `waterfloat` is present and we are dealing with a `Strider`, `ignorewater` and `alwaysactive` are set to true on top of the ignoring the collider of the map's `waterfloat` with this entity. Finally, the y position of the entity is set to the one of the `waterfloat`
|
||||
* If the `animid` is `Scorpion` and we are at Giant's Lair, the `basestate` is overridden to 150 and `walkstate` to 151 which makes them render differently.
|
||||
|
||||
@@ -7,6 +7,7 @@ Essentially, `dead` means the Death process started while `iskill` means it is a
|
||||
First, `nocondition` and `dead` are set to true. [BreakIce](Freeze%20handling.md#breakice) is called and [StopForceMove](../EntityControl%20Methods.md#stopforcemove) is too without smoothing and default state. This not only unfreezes the entity if it was, but also stops any coroutine force move that was running. After, the `rigid`'s velocity is zeroed out and the `digpart` destroyed if there were any left.
|
||||
|
||||
From there, if the entity had an `npcdata`, it is handled in its own section:
|
||||
|
||||
- STOP is called on the npcdata, but this doesn't do anything because `dead` was just set to true
|
||||
- If npcdata.`regionalflag` isn't negative, the corresponding [regionaflag](../../../Flags%20arrays/Regionalflags.md) slot is set to true
|
||||
- If npcdata.`disguiseobj` exists, it is destroyed
|
||||
@@ -75,10 +76,10 @@ This type is only used in BattleControl.StartBattle as it is set to all `playere
|
||||
- The `anim` is disabled
|
||||
- A frame is yielded
|
||||
- For each Transform descendant to the `sprite` (or the `model` if it exists) except the first one:
|
||||
- A RigidBody is added to the transform
|
||||
- The transform gets rooted to the scene
|
||||
- The RigidBody gets its gravity disabled with a velocity of RandomItemBounce(2.5, 12.0)
|
||||
- The object gets destroyed in a second
|
||||
- A RigidBody is added to the transform
|
||||
- The transform gets rooted to the scene
|
||||
- The RigidBody gets its gravity disabled with a velocity of RandomItemBounce(2.5, 12.0)
|
||||
- The object gets destroyed in a second
|
||||
- A second is yielded
|
||||
|
||||
### Shrink
|
||||
@@ -113,8 +114,8 @@ The same than Shrink, but no DeathSmoke particles are played.
|
||||
## After the `destroytype` specific logic (doesn't occur for `PlayeDeath`)
|
||||
- All frames are yielded while in a `pause` or it's not a `battle` entity while we are in a battle
|
||||
- For anything except an `npcdata` of type [Enemy](../../NPCControl/Enemy.md) with an `eventid` of 0 or below (meaning no `respawntimer` feature):
|
||||
- If `spitmoney` is above 0, the berries drop logic is performed (see the section below for details)
|
||||
- If `npcdata` has a non empty `vectordata` without a [SetPath](../../NPCControl/ActionBehaviors/SetPath.md) or [SetPathJump](../../NPCControl/ActionBehaviors/SetPathJump.md) behaviors, the item drop logic is performed (see the section below for details)
|
||||
- If `spitmoney` is above 0, the berries drop logic is performed (see the section below for details)
|
||||
- If `npcdata` has a non empty `vectordata` without a [SetPath](../../NPCControl/ActionBehaviors/SetPath.md) or [SetPathJump](../../NPCControl/ActionBehaviors/SetPathJump.md) behaviors, the item drop logic is performed (see the section below for details)
|
||||
- A frame is yielded
|
||||
- If this GameObject is null (which shouldn't happen), the coroutine is exited early with a yield break
|
||||
- If the `destroytype` isn't `KO`, `SpinKO` or `None`, the entity position is set offscreen at (0.0, 9999.0, 0.0) followed by the destruction of the object (only if we aren't in a battle)
|
||||
@@ -129,6 +130,7 @@ The following is performed until `spitmoney` amount of berries worth total have
|
||||
|
||||
### Item drop logic
|
||||
The `specialenemy` cases are handled. These are hardcoded [enemy](../../../Enums%20and%20IDs/Enemies.md) ids with hardcoded odds to drop an [item](../../../Enums%20and%20IDs/Items.md) from an hardcoded list of ids with uniform probability each. The way it works is the first occurence of a special enemy in `lastdefeated` (if one exists) will test for a potential drop. If multiple exists, only the first is tested once so if it fails, others will not be attempted to drop. Here are the the hardcoded ids in question as well as their odds:
|
||||
|
||||
|Enemy|% to drop|Possible item drops|
|
||||
|-----|---------|-------------------|
|
||||
|`GoldenSeedling`|100|`TangyBerry`|
|
||||
@@ -136,6 +138,7 @@ The `specialenemy` cases are handled. These are hardcoded [enemy](../../../Enums
|
||||
|`ToeBiter`|40|`HoneydLeaf`, `GlazedHoney`, `HeartyBreakfast`, `YamBread`, `BakedYam`, `Pudding`, `RoastBerry`, `ClearBomb`, `SleepBomb`, `LeafSalad`, `FrozenSalad`, `MushroomStick`, `ShavedIce`, `BurlyChips`|
|
||||
|
||||
If a drop occurs:
|
||||
|
||||
- [CreateItem](../../NPCControl/ObjectTypes/Item.md#entitycontrolcreateitem) is called which creates an [Item](../../NPCControl/ObjectTypes/Item.md) NPCControl object at `spritetansform` position + (0.0, 0.5, 0.0) with the item type being 0 (standard item), the item id being a randomly chosen (uniform odds) element from the applicable possible drop list, the direction being RandomItemBounce(4.0, 10.0) for 600 frames.
|
||||
- The collisions between the item's entity.`ccol` and the item's entity.`detect` or itself are ignored for 5.0 seconds
|
||||
- The same RandomBounce vector obtined earlier is set to the item's entity.`rigid` vecity on the next frame
|
||||
@@ -143,6 +146,7 @@ If a drop occurs:
|
||||
Whether or not the drop failed or succeeded, the enemy is removed from the `lastdefeated` array. From there, `lastdefeated` is reset to a new list (making the last deletion useless).
|
||||
|
||||
An random number is generated where the upper (exclusive) bound is the length of npcdata.`vectordata`, but the lower (inclusive) bound is determined based on some factors:
|
||||
|
||||
- Having the Bug Me Not! [medal](../../../Enums%20and%20IDs/Medal.md) equipped makes it -7 (this takes priority over the ones below)
|
||||
- Having the Hard Mode medal unequipped while [flag](../../../Flags%20arrays/flags.md) 614 (HARDEST) is false makes it -3
|
||||
- If neither of the cases above applies (meaning Hard Mode is equipped or HARDEST is active while Bug Me Not! is unequipped), it's -1
|
||||
@@ -152,11 +156,13 @@ However, that index gets overriden if `vectordata` contains at least one element
|
||||
This index is used for a potential item drop. If the index is negative, no drops happen. If it's positive, but the y component of the corresponding npcdata.`vectordata` isn't negative, then the drop only happens if that y component floored corresponds to a [flag](../../../Flags%20arrays/flags.md) slot whose value is true. If it's false, the drop doesn't happen.
|
||||
|
||||
If the drop happens:
|
||||
|
||||
- [CreateItem](../../NPCControl/ObjectTypes/Item.md#entitycontrolcreateitem) is called which creates an [Item](../../NPCControl/ObjectTypes/Item.md) NPCControl object at `spritetansform` position + (0.0, 0.5, 0.0) with the item type being 0 (standard item), the item id being the chosen npcdata.`vectordata` x component using the index generated earlier, the direction being RandomItemBounce(4.0, 10.0) for 600 frames.
|
||||
- The collisions between the item's entity.`ccol` and the item's entity.`detect` or itself are ignored for 5.0 seconds
|
||||
- The same RandomBounce vector obtined earlier is set to the item's entity.`rigid` vecity on the next frame
|
||||
|
||||
However, if the corresponding npcdata.`vectordata` y component is -2 (meaning its index was overriden earlier), then it means this is a special key item drop that will always be dropped. The procedure to drop it is the same, but with a few changes:
|
||||
|
||||
- The item type is 1 (key item) instead of 0 (standard item)
|
||||
- -1 is the timer value which means the [Item](../../NPCControl/ObjectTypes/Item.md) never expires even after 600 frames
|
||||
- After the [CreateItem](../../NPCControl/ObjectTypes/Item.md#entitycontrolcreateitem) call, the item's `activationflag` is set to npcdata.`limit[0]`
|
||||
|
||||
@@ -53,9 +53,9 @@ From there, we can now check the if entity should not move or move towards `foll
|
||||
|
||||
* The player is present and not dashing
|
||||
* One or more of the following is true:
|
||||
* We are currently in a stealth section ([flags](../../../Flags%20arrays/flags.md) 401), the map's closemove is true and this entity is part of the `mainparty`
|
||||
* This entity is part of the `mainparty` and the player has a parent
|
||||
* The player has forceclosemove to true
|
||||
* We are currently in a stealth section ([flags](../../../Flags%20arrays/flags.md) 401), the map's closemove is true and this entity is part of the `mainparty`
|
||||
* This entity is part of the `mainparty` and the player has a parent
|
||||
* The player has forceclosemove to true
|
||||
|
||||
The result is that the entity will attempt to be twice as close than normal under these conditions.
|
||||
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
LateStart is a method that is only called on the first [LateUpdate](../Update%20process/Unity%20events/LateUpdate.md) cycle of the entity. This is tracked using the `setup` field which is only set to true at the end of this method.
|
||||
|
||||
* Check the tag of the entity
|
||||
* For `Follower`, `PFollower`, `Player`, `NPC` and `Enemy`, `movesmoke` is initialised unless it is an item. Either way, the `anim`'s cullingMode is set to CullCompletely which disabled animations when not visible
|
||||
* For `Follower` and `PFollower`, [CreateDetector](../EntityControl%20Methods.md#CreateDetector) is called with a size of (0.0, 0.7, 0.3) and a center of (0.0, 0.5, 0.65). Collisions between `detect` and the `following` entity are ignored before setting `isfollower` to true.
|
||||
* For `Player`, `isplayer` is set to true and CreateShield called if it is the battle entity version of the player which initializes `bubbleshield` if it hasn't been already
|
||||
* For `Follower`, `PFollower`, `Player`, `NPC` and `Enemy`, `movesmoke` is initialised unless it is an item. Either way, the `anim`'s cullingMode is set to CullCompletely which disabled animations when not visible
|
||||
* For `Follower` and `PFollower`, [CreateDetector](../EntityControl%20Methods.md#CreateDetector) is called with a size of (0.0, 0.7, 0.3) and a center of (0.0, 0.5, 0.65). Collisions between `detect` and the `following` entity are ignored before setting `isfollower` to true.
|
||||
* For `Player`, `isplayer` is set to true and CreateShield called if it is the battle entity version of the player which initializes `bubbleshield` if it hasn't been already
|
||||
* If it's an [item entity](../Item%20entity.md), set `overrideanim` and `overrridejump` as well as `oldstate` to -1 (`None`) and call `CreateFeet` which will initialise `feet` and set this entity as its parent
|
||||
* Set `originalmap` to the current map
|
||||
* If there is an `npcdata`
|
||||
* Set `npcdata`'s `currentdialogueindex` to NPCControl.GetDialogueIndex which is a very cut down version of [GetDialogue](../../NPCControl/Notable%20methods/GetDialogue.md#getdialogue) that only supports `npcdata.overridediag` and will only return the first applicable dialogue line id or -1 if none applied
|
||||
* If the map entity is a [PushRock](../../NPCControl/ObjectTypes/PushRock.md) with `internalcollider` present, ensure `feet` is initialised and call `CreateFeet` if not while also ignoring all collisions between `feet` and each `internalcollider`
|
||||
* Set `npcdata`'s `currentdialogueindex` to NPCControl.GetDialogueIndex which is a very cut down version of [GetDialogue](../../NPCControl/Notable%20methods/GetDialogue.md#getdialogue) that only supports `npcdata.overridediag` and will only return the first applicable dialogue line id or -1 if none applied
|
||||
* If the map entity is a [PushRock](../../NPCControl/ObjectTypes/PushRock.md) with `internalcollider` present, ensure `feet` is initialised and call `CreateFeet` if not while also ignoring all collisions between `feet` and each `internalcollider`
|
||||
* If by this point, `feet` hasn't been initialised and the entity is a `Follower`, `PFollower`, `isplayer`, `NPC`, `Enemy` or an `npcdata` of type [PushRock](../../NPCControl/ObjectTypes/PushRock.md) or [Item](../../NPCControl/ObjectTypes/Item.md), `CreateFeet` is called
|
||||
* Set the `transform`'s position to `startpos` if it was assigned before or set `startpos` to the `transform`'s position if it wasn't
|
||||
* Set `startbf`, `startbs` and `truescale` to `bobrange`, `bobspeed` and `startscale` respectively
|
||||
|
||||
@@ -2,16 +2,16 @@
|
||||
This is the LateUpdate of EntityControl. This is the main update loop of the component and it is done on late due to the guarantee that coroutines have all ran by then so anything that could have edited the fields like the [animstate](../../Animations/animstate.md) have done so already.
|
||||
|
||||
* Every 3 frames
|
||||
* If paused, ensure the `transform`'s position is `pausepos` unless `activeonpause` is true, we are in an event, `iskill` is true or `dead` is true
|
||||
* Calls `UpdateCamPos` which updates `incamera` with whether the entity is in the main camera range (ranging from (-0.6, -1.25) to (1.6, 2.25) in viewport coordinate while also being higher than -1 on the z axis) or true if `alwaysactive` is true, `camdistance` to the distance of the entity to the main camera and `campos` being the viewport position of the entity using the main camera
|
||||
* If paused, ensure the `transform`'s position is `pausepos` unless `activeonpause` is true, we are in an event, `iskill` is true or `dead` is true
|
||||
* Calls `UpdateCamPos` which updates `incamera` with whether the entity is in the main camera range (ranging from (-0.6, -1.25) to (1.6, 2.25) in viewport coordinate while also being higher than -1 on the z axis) or true if `alwaysactive` is true, `camdistance` to the distance of the entity to the main camera and `campos` being the viewport position of the entity using the main camera
|
||||
* Ensure `latetrans`'s position is set to `latepos` when applicable
|
||||
* If we aren't paused and there's a `forcemove` in progress, handle the failsafe logic
|
||||
* Decrease the `forcetimer` by framestep if `playerentity` is true or that either `alwaysactive` is true or the entity is `incamera` and is within 30.0 units on the z axis unless `disabletimer` is true which will bypass this decrease for any entity except `playerentity`
|
||||
* If the `forcetimer` expired, the entity isn't `digging` and the player isn't free or it's not a `playerentity` then the failsafe will take effect by setting the `transform`'s position to `forcetarget`. Smokes will appear at the entity position before the failsafe and at `forcetarget` after the failsafe if it isn't `shrink` and its scale's magnitude is higher than 0.2.
|
||||
* Decrease the `forcetimer` by framestep if `playerentity` is true or that either `alwaysactive` is true or the entity is `incamera` and is within 30.0 units on the z axis unless `disabletimer` is true which will bypass this decrease for any entity except `playerentity`
|
||||
* If the `forcetimer` expired, the entity isn't `digging` and the player isn't free or it's not a `playerentity` then the failsafe will take effect by setting the `transform`'s position to `forcetarget`. Smokes will appear at the entity position before the failsafe and at `forcetarget` after the failsafe if it isn't `shrink` and its scale's magnitude is higher than 0.2.
|
||||
* Handle the numb animation update logic if it is a battle entity while we are in a battle, the entity isn't `dead` or `iskill`, the battledata of the entity at `battleid` indicates `isnumb` and the battle hasn't `cancelupdate` by calling Numb. This method handles setting the [animstate](../../Animations/animstate.md) accordingly as well as randomly displacing the entity every once in a while with a yellow color
|
||||
* Handles the `bubbleshield` position update if it is present
|
||||
* If the scale's magnitude is higher than 0.15, the default is to set the local position of the `bubbleshield` to (0.0, `height` + 1.25, 0.0), but `overrideshieldpos` being true can change this to be (`overrideshieldpos`.x, `height` + `overrideshieldpos`.y, `overrideshieldpos`.z)
|
||||
* Otherwise, the local position is set offscreen to (0.0, -999.0, 0.0)
|
||||
* If the scale's magnitude is higher than 0.15, the default is to set the local position of the `bubbleshield` to (0.0, `height` + 1.25, 0.0), but `overrideshieldpos` being true can change this to be (`overrideshieldpos`.x, `height` + `overrideshieldpos`.y, `overrideshieldpos`.z)
|
||||
* Otherwise, the local position is set offscreen to (0.0, -999.0, 0.0)
|
||||
* If the `hpbar` is present and active, ensure its local position is at (0.0, -0.5 + camoffset.y - battlecampos.y, 0.0) unless it's a `KeyR` which changes the x to 0.5 or a `Pitcher` which changes the x to -0.5
|
||||
* If the `sprite` is present and the `animid` isn't `None` (-1), [RefreshTrail](../RefreshTrail.md) is called which will update the `traildata` according to `trail`
|
||||
* Ensure the `transform` is childed to the map if it's a `tempfollower` and the `transform` doesn't have a parent already
|
||||
@@ -19,28 +19,28 @@ This is the LateUpdate of EntityControl. This is the main update loop of the com
|
||||
* As long as the game isn't paused, call [Follow](../../Notable%20methods/Follow.md) which updates the following procedure
|
||||
* If `alwaysflip` is true, call [UpdateFlip](../UpdateFlip.md)
|
||||
* If the game is unpaused and `incamera`, the `incamera` update will happen if we are in an event OR that the `campos` z is less than 25.0 OR less than 30.0 only if the `npcdata`'s `startlife` is smaller than 50.0 / not present
|
||||
* Assign `truescale` to `startscale`
|
||||
* If the `icecube` is present, set its scale by a lerp of its current scale to `freezesize` with a factor of framestep * 0.25 and set its position by `freezeoffset` + Vector3.up * `height` or by (`freezeoffset`.x + Random.Range(-0.1, 0.1), `freezeoffset`.y + `height`, `freezeoffset`.z + Random.Range(-0.1, 0.1)) if `shakeice`
|
||||
* If `springcooldown` is active while the `rigid`'s velocity is descending on the y axis or `onground` is true, deactivate the cooldown
|
||||
* General update methods are called under conditions:
|
||||
* [UpdateGround](../UpdateGround.md), [UpdateAirAnim](../UpdateAirAnim.md) and [UpdateVelocity](../UpdateVelocity.md) are called every 2 frames except for `battle` entity or the `npcdata` is not NPC / not present where they will be called regardless of the current frame
|
||||
* [UpdateGeneralAnim](../UpdateGeneralAnim.md) is called every 2 frames
|
||||
* [UpdateEmoticon](../UpdateEmoticon.md) is called when in an event or it is a `battle` entity or every 2 frames
|
||||
* [UpdateMoveSmoke](../UpdateMoveSmoke.md) is called every 3 frames
|
||||
* [RefreshShadow](../RefreshShadow.md) is called when `isfollower` is true and the player is flying OR that there is no `npcdata` OR that it has one but it's also an Enemy, a SemiNPC for every 10 frames or it's an NPC/Object every 2 frames in addition that the `insideid` matches the current one
|
||||
* [UpdateStatusIcons](../UpdateStatusIcons.md) and [UpdateSound](../UpdateSound.md) are always called
|
||||
* [UpdateFlip](../UpdateFlip.md) is called either when we are not in a battle or the entity itself is a `battle` entity (if `alwaysflip` was true, this is means this can be called a second time)
|
||||
* Assign `truescale` to `startscale`
|
||||
* If the `icecube` is present, set its scale by a lerp of its current scale to `freezesize` with a factor of framestep * 0.25 and set its position by `freezeoffset` + Vector3.up * `height` or by (`freezeoffset`.x + Random.Range(-0.1, 0.1), `freezeoffset`.y + `height`, `freezeoffset`.z + Random.Range(-0.1, 0.1)) if `shakeice`
|
||||
* If `springcooldown` is active while the `rigid`'s velocity is descending on the y axis or `onground` is true, deactivate the cooldown
|
||||
* General update methods are called under conditions:
|
||||
* [UpdateGround](../UpdateGround.md), [UpdateAirAnim](../UpdateAirAnim.md) and [UpdateVelocity](../UpdateVelocity.md) are called every 2 frames except for `battle` entity or the `npcdata` is not NPC / not present where they will be called regardless of the current frame
|
||||
* [UpdateGeneralAnim](../UpdateGeneralAnim.md) is called every 2 frames
|
||||
* [UpdateEmoticon](../UpdateEmoticon.md) is called when in an event or it is a `battle` entity or every 2 frames
|
||||
* [UpdateMoveSmoke](../UpdateMoveSmoke.md) is called every 3 frames
|
||||
* [RefreshShadow](../RefreshShadow.md) is called when `isfollower` is true and the player is flying OR that there is no `npcdata` OR that it has one but it's also an Enemy, a SemiNPC for every 10 frames or it's an NPC/Object every 2 frames in addition that the `insideid` matches the current one
|
||||
* [UpdateStatusIcons](../UpdateStatusIcons.md) and [UpdateSound](../UpdateSound.md) are always called
|
||||
* [UpdateFlip](../UpdateFlip.md) is called either when we are not in a battle or the entity itself is a `battle` entity (if `alwaysflip` was true, this is means this can be called a second time)
|
||||
* Otherwise, the inactive update will happen
|
||||
* The entity is muted when applicable when `soundonpause` is true OR that it's not a battle battle and it either has no `npcdata` or it has one, but it's a `MusticRange` Object, otherwise, [UpdateSound](../UpdateSound.md) is called instead
|
||||
* Reset the `emoticon` to none and the `emoticoncooldown` to 0.0 when applicable
|
||||
* Deactivate the `movesmoke` if it is present and enabled
|
||||
* The entity is muted when applicable when `soundonpause` is true OR that it's not a battle battle and it either has no `npcdata` or it has one, but it's a `MusticRange` Object, otherwise, [UpdateSound](../UpdateSound.md) is called instead
|
||||
* Reset the `emoticon` to none and the `emoticoncooldown` to 0.0 when applicable
|
||||
* Deactivate the `movesmoke` if it is present and enabled
|
||||
* This is the general update handling when unpaused that applies to all entities
|
||||
* Every 3 frames, `UpdateRotater` is called which will make sure the `rotater`'s y angle matches the main camera one unless `lockrotater` is true. If we were not in an event [UpdateCollider](../UpdateCollider.md) is called before it, but because this one only process every 2 frames, it will actually only process every 6 frames effectively.
|
||||
* Rendering updates happen if the entity is `incamera`, it is a `battle` entity or that we are in an event
|
||||
* [UpdateHeight](../UpdateHeight.md) is called when it's a battle entity or we are in an event or `alwaysactive` is true or it has no `npcdata` or it has one, but it's not an NPC or it is an NPC, but the `startlife` is below 50.0
|
||||
* [AnimSpecificQuirks](../../Animations/AnimSpecific.md#animspecificquirks) and [UpdateSprite](../UpdateSprite.md) are called
|
||||
* `flyinganim` is set to true if the `height` is higher than 0.1 unless `overridefly` is true which forces it to false
|
||||
* If we aren't in an event, then `offgroundframes` is increased by framestep if it hasn't reached 1000.0 and that `onground` is false, otherwise, it is set to 0.0. If we are in an event, that it is decreased by framestep if `onground` is true and it hasn't gone below 0.0
|
||||
* If the `jumpcooldown` has expired and `stopspinonground` is true, it is set to false on top of zeroing out `spin`
|
||||
* Every 3 frames, `UpdateRotater` is called which will make sure the `rotater`'s y angle matches the main camera one unless `lockrotater` is true. If we were not in an event [UpdateCollider](../UpdateCollider.md) is called before it, but because this one only process every 2 frames, it will actually only process every 6 frames effectively.
|
||||
* Rendering updates happen if the entity is `incamera`, it is a `battle` entity or that we are in an event
|
||||
* [UpdateHeight](../UpdateHeight.md) is called when it's a battle entity or we are in an event or `alwaysactive` is true or it has no `npcdata` or it has one, but it's not an NPC or it is an NPC, but the `startlife` is below 50.0
|
||||
* [AnimSpecificQuirks](../../Animations/AnimSpecific.md#animspecificquirks) and [UpdateSprite](../UpdateSprite.md) are called
|
||||
* `flyinganim` is set to true if the `height` is higher than 0.1 unless `overridefly` is true which forces it to false
|
||||
* If we aren't in an event, then `offgroundframes` is increased by framestep if it hasn't reached 1000.0 and that `onground` is false, otherwise, it is set to 0.0. If we are in an event, that it is decreased by framestep if `onground` is true and it hasn't gone below 0.0
|
||||
* If the `jumpcooldown` has expired and `stopspinonground` is true, it is set to false on top of zeroing out `spin`
|
||||
* `lastpos` is set to the `transform`'s position
|
||||
* `oldground` is set to `onground`
|
||||
|
||||
@@ -2,24 +2,24 @@
|
||||
This is the Update of EntityControl. It doesn't do as much as [LateUpdate](LateUpdate.md)
|
||||
|
||||
* Check if the entity should receive updates which only happens when unpaused, minipause isn't active, the [message](../../../../SetText/Notable%20states.md#message) lock is released and the entity isn't dead. This can be overriden with `activeonpause`
|
||||
* Follow the standard animation speed update logic unless `overrideanimspeed` is true which will set the animation speed to 1.0 if there's no `icecube` and to 0.0 if there is one on top of forcing the [animstate](../../Animations/animstate.md) to `Hurt`
|
||||
* Make sure the `sprite` is disabled if this is the player entity and is a submarine, otherwise
|
||||
* Toggle the sprite being enabled if the `icooldown` hasn't expired yet and the player is free (meaning it is present, no minipause or pause, not in an event, the [message](../../../../SetText/Notable%20states.md#message) lock is released, and the player isn't digging)
|
||||
* Ensure the sprite is enabled if it's not an item and it has no `npcdata` or it has one and it doesn't have a `disguiseobj`
|
||||
* Ensure the child of the sprite are enabled or disabled according to the main sprite's enabled unless the `npcdata` is present and its `trapped` is true
|
||||
* Decrease the `icooldown` with the framestep
|
||||
* Handle the restore of the entity when unpausing happend:
|
||||
* The `rigid`'s useGravity is set to `lastgravity`
|
||||
* The `sound`'s volume is set to `lastvolume`
|
||||
* The `rigid`'s velocity is set to `lastvelocity`
|
||||
* `lastvelocity` and `pausepos` are put back to null
|
||||
* Follow the standard animation speed update logic unless `overrideanimspeed` is true which will set the animation speed to 1.0 if there's no `icecube` and to 0.0 if there is one on top of forcing the [animstate](../../Animations/animstate.md) to `Hurt`
|
||||
* Make sure the `sprite` is disabled if this is the player entity and is a submarine, otherwise
|
||||
* Toggle the sprite being enabled if the `icooldown` hasn't expired yet and the player is free (meaning it is present, no minipause or pause, not in an event, the [message](../../../../SetText/Notable%20states.md#message) lock is released, and the player isn't digging)
|
||||
* Ensure the sprite is enabled if it's not an item and it has no `npcdata` or it has one and it doesn't have a `disguiseobj`
|
||||
* Ensure the child of the sprite are enabled or disabled according to the main sprite's enabled unless the `npcdata` is present and its `trapped` is true
|
||||
* Decrease the `icooldown` with the framestep
|
||||
* Handle the restore of the entity when unpausing happend:
|
||||
* The `rigid`'s useGravity is set to `lastgravity`
|
||||
* The `sound`'s volume is set to `lastvolume`
|
||||
* The `rigid`'s velocity is set to `lastvelocity`
|
||||
* `lastvelocity` and `pausepos` are put back to null
|
||||
* Handle pausing updates, if we are paused
|
||||
* Unless `lastvelocity` already had a value (which means this is the first frame of being paused) the pause states are saved
|
||||
* `pausepos` is set to the `transform`'s position
|
||||
* `lastgravity` is set to the `rigid`'s useGravity
|
||||
* `lastvolume` is set to `sound`'s volume
|
||||
* `lastvelocity` is set to the `rigid`'s velocity
|
||||
* gravity is disabled on the `rigid`
|
||||
* The `sound` is muted
|
||||
* The `rigid`'s velocity is zeroed
|
||||
* If not in a battle, ensure the animation speed is set to 0.0 and then call [StopMoving](../../EntityControl%20Methods.md#StopMoving) with the current [animstate](../../Animations/animstate.md) which will zero the `rigid`'s velocity and the `deltavelocity`. Otherwise, ensure the animation speed is 1.0
|
||||
* Unless `lastvelocity` already had a value (which means this is the first frame of being paused) the pause states are saved
|
||||
* `pausepos` is set to the `transform`'s position
|
||||
* `lastgravity` is set to the `rigid`'s useGravity
|
||||
* `lastvolume` is set to `sound`'s volume
|
||||
* `lastvelocity` is set to the `rigid`'s velocity
|
||||
* gravity is disabled on the `rigid`
|
||||
* The `sound` is muted
|
||||
* The `rigid`'s velocity is zeroed
|
||||
* If not in a battle, ensure the animation speed is set to 0.0 and then call [StopMoving](../../EntityControl%20Methods.md#StopMoving) with the current [animstate](../../Animations/animstate.md) which will zero the `rigid`'s velocity and the `deltavelocity`. Otherwise, ensure the animation speed is 1.0
|
||||
|
||||
@@ -4,7 +4,7 @@ This update method is called by [LateUpdate](Unity%20events/LateUpdate.md). It u
|
||||
The `ccol` physics material update applies except if it's a `npcdata` of `Pushrock`. The staticFriction and dynamicFriction of the material are either set to 1.0 or 0.0 depending on specific conditions:
|
||||
|
||||
* If `onground`, the `deltavelocity`'s magnitude is lower than 0.2 and `jumpcooldown` is expired
|
||||
* Then 1.0 is set to the friction unless the `transform` is the player's and the [animstate](../Animations/animstate.md) isn't `Walk` and `hitwall` is false in which case, 0.0 is set to the friction values
|
||||
* Then 1.0 is set to the friction unless the `transform` is the player's and the [animstate](../Animations/animstate.md) isn't `Walk` and `hitwall` is false in which case, 0.0 is set to the friction values
|
||||
* 0.0 is set to the friction values otherwise.
|
||||
|
||||
Finally, if the `jumpcooldown` is still active, it is decreased by framestep.
|
||||
|
||||
@@ -50,11 +50,11 @@ Finally, this is where the [SetAnim](../Animations/SetAnim.md) call happens. The
|
||||
* The `f` argument is sent if `overridefly` is false, the `height` is higher than 0.1 and the [animstate](../Animations/animstate.md) is among the following: `Idle`, `Walk`, `ItemGet`, `Chase`, `ItemWalk`, `Sleep`, `Hurt`, `BattleIdle` or `Woobly`. The `ft` argument is sent if on top of this if `notalk` is false and the entity is `talking`.
|
||||
* Only the `t` argument is sent if the [animstate](../Animations/animstate.md) is a [Predefined animations names](../Animations/animstate.md#predefined-animations-names), the entity is `talking` while `notalk` is false. This also set `backsprite` to false.
|
||||
* Only the `b` argument is sent under the following conditions:
|
||||
* We aren't in PUSHROCK
|
||||
* We either aren't in a battle or we are in a battle event
|
||||
* `backsprite` is true
|
||||
* The [animstate](../Animations/animstate.md) is `Idle`, `Walk` or `Jump`
|
||||
* The `originalid` is `Bee`, `Beetle`, `Moth`, `Madeleine` or `BLANK`
|
||||
* We aren't in PUSHROCK
|
||||
* We either aren't in a battle or we are in a battle event
|
||||
* `backsprite` is true
|
||||
* The [animstate](../Animations/animstate.md) is `Idle`, `Walk` or `Jump`
|
||||
* The `originalid` is `Bee`, `Beetle`, `Moth`, `Madeleine` or `BLANK`
|
||||
* If none of the above applies, no arguments are sent
|
||||
|
||||
After the [SetAnim](../Animations/SetAnim.md) call, `backsprite` is set to false for any [animstate](../Animations/animstate.md) that isn't `Idle`, `Walk`, `Jump` or `Fall`.
|
||||
|
||||
@@ -7,6 +7,7 @@ The actual execution of the behavior is done by [DoBehavior](Notable%20methods/D
|
||||
|
||||
## Enum table
|
||||
The following is a table of the different enum values (NOT REFERENCED means the game never reference the value meaning it has not logic backing it, UNUSED means the behavior has logic, but it is either dead or not practically used under normal gameplay):
|
||||
|
||||
|Value|Name|Summary|
|
||||
|----:|----|----------|
|
||||
|0|[None](ActionBehaviors/None.md)|Stops any force move on the entity.|
|
||||
@@ -14,34 +15,34 @@ The following is a table of the different enum values (NOT REFERENCED means the
|
||||
|2|[ChasePlayer](ActionBehaviors/ChasePlayer.md)|Approach the player as close as possible within the `radiuslimit` or until there is no more ground to move in the direction of the player.|
|
||||
|3|[FleeFromPlayer](ActionBehaviors/FleeFromPlayer.md)|Stops any force move on the entity and have it move towards the opposide direction from the player.|
|
||||
|4|[TurnRandomly](ActionBehaviors/TurnRandomly.md)|Stops any force move on the entity and periodically causes the entity.`flip` to toggle which turns the entity using a somewhat random time interval.|
|
||||
|5|[Wander](ActionBehaviors/Wander.md)|Periodically performs a [MoveTowards](../../EntityControl/EntityControl%20Methods.md#movetowards) call after a random amount of time passed on the entity to a random position or the closest possible before unable to move further towards it. The range of movement, maximum time period to wait between wanders and the max distance to move to between wanders are all configurable.|
|
||||
|5|[Wander](ActionBehaviors/Wander.md)|Periodically performs a [MoveTowards](../EntityControl/EntityControl%20Methods.md#movetowards) call after a random amount of time passed on the entity to a random position or the closest possible before unable to move further towards it. The range of movement, maximum time period to wait between wanders and the max distance to move to between wanders are all configurable.|
|
||||
|6|[FaceAwayFromPlayer](ActionBehaviors/FaceAwayFromPlayer.md)|Stops any force move on the entity and causes the entity.`flip` to be set such that the sprite faces the opposite direction of the player horizontally.|
|
||||
|7|[TurnFixedInterval](ActionBehaviors/TurnFixedInterval.md)|Stops any force move on the entity and periodically causes the entity.`flip` to toggle which turns the entity using a fixed time interval.|
|
||||
|8|[Disguise](ActionBehaviors/Disguise.md)|A behavior where the map entity has a special `disguiseobj` that will replace its normal entity.`sprite` appearence until the behavior is switched away from which reveals the entity.`sprite` (usually by going into the `inrange` one). After coming back to this behavior (usually by going out of `inrange`), the entity will move back to its `startpos` and put its disguise on again.|
|
||||
|9|[DisguiseOnce](ActionBehaviors/DisguiseOnce.md)|The same than [Disguise](Disguise.md), but if it's the default behavior, it becomes [Wander](Wander.md) whenever the player gets `inrange` and the `disguiseobj` is destroyed.|
|
||||
|9|[DisguiseOnce](ActionBehaviors/DisguiseOnce.md)|The same than `Disguise`, but if it's the default behavior, it becomes `Wander` whenever the player gets `inrange` and the `disguiseobj` is destroyed.|
|
||||
|10|FollowPlayer|NOT REFERENCED|
|
||||
|11|[WalkAwayFromPlayer](ActionBehaviors/WalkAwayFromPlayer.md)|UNUSED, This is an alias of [FleeFromPlayer](FleeFromPlayer.md).|
|
||||
|11|[WalkAwayFromPlayer](ActionBehaviors/WalkAwayFromPlayer.md)|UNUSED, This is an alias of `FleeFromPlayer`|
|
||||
|12|[FaceAhead](ActionBehaviors/FaceAhead.md)|Stops any force move on the entity and causes the entity to face towards the right vector of this entity (towards their x axis facing direction).|
|
||||
|13|[FaceBehind](ActionBehaviors/FaceBehind.md)|Stops any force move on the entity and causes the entity to face towards the left vector of this entity (the opposite direction of their x axis direction)|
|
||||
|14|[FaceUp](ActionBehaviors/FaceUp.md)|Stops any force move on the entity and causes the entity to face towards the forward vector of this entity (usually away from the camera).|
|
||||
|15|[FaceDown](ActionBehaviors/FaceDown.md)|Stops any force move on the entity and causes the entity to face towards the backward vector of this entity (usually towards the camera).|
|
||||
|16|[SetPath](ActionBehaviors/SetPath.md)|Periodically performs [MoveTowards](../../EntityControl/EntityControl%20Methods.md#movetowards) calls on the entity using a fixed configurable interval between moves and the path being made of position nodes defined in `vectordata`.|
|
||||
|17|[ChargeAtPlayer](ActionBehaviors/ChargeAtPlayer.md)|Charges at the player with `attacking` set to true during the movement towards the player (this will allow an [Enemy](../NPCType.md#enemy) to initiate a battle with the advantage if it collides with the player and all conditions are met to start a battle with the advantage).|
|
||||
|18|[ChargeAtPlayerFlipSprite](ActionBehaviors/ChargeAtPlayerFlipSprite.md)|The same then [ChargeAtPlayer](ChargeAtPlayer.md), but right after the [MoveTowards](../../EntityControl/EntityControl%20Methods.md#movetowards) call on the entity, the entity.`sprite` has its angles set to (0.0, the y angles facing the player + 90.0, 0.0) with an `overrideonlyflip` which locks the entity.`sprite` facing direction until the charge part of the coroutine is over.|
|
||||
|19|[ShootProjectile](ActionBehaviors/ShootProjectile.md)|Attacks the player by shooting an OverworldProjectile which can, under the right conditions, start a battle with advantage. The specifics of the projectile logic is dependant on the [animid](../../../Enums%20and%20IDs/AnimIDs.md) and only a few have a logic defined for this behavior.|
|
||||
|20|[ShootProjectilePredict](ActionBehaviors/ShootProjectilePredict.md)|UNUSED, An alias of [ShootProjectile](ShootProjectile.md).|
|
||||
|21|[ChargeAndAttack](ActionBehaviors/ChargeAndAttack.md)|The same than [ChasePlayer](ChasePlayer.md), but also attacks the player (with `attacking` set to true during the attack) where the actions depends on the [AnimID](../../../Enums%20and%20IDs/AnimIDs.md) when getting closer than a configurable threshold. Only a few animIds have an attack logic defined for this behavior.|
|
||||
|22|[AlwaysWander](ActionBehaviors/AlwaysWander.md)|UNUSED, A very cut down version of [wander](Wander.md) where the entity will always, when it can, move somewhere on the next DoBehavior cycle even if it is in the process of moving already.|
|
||||
|23|[Unmoveable](ActionBehaviors/Unmoveable.md)|Prevents an [Enemy](../NPCType.md#enemy) with this behavior (either default or `inrange`) to not move during the [Dizzy](../Notable%20methods/Dizzy.md) process. This doesn't have any logic, its presence is what affects the NPCControl.|
|
||||
|24|[ChargeAttackUnderground](ActionBehaviors/ChargeAttackUnderground.md)|The same than [ChargeAndAttack](ChargeAndAttack.md), but the behavior always makes the entity `digging` when not attacking and it can only attack after 30.0 frames of `digtime`.|
|
||||
|25|[WanderUnderground](ActionBehaviors/WanderUnderground.md)|The same than [Wander](Wander.md), but the entity immediately starts digging underground before actually wandering.|
|
||||
|26|[StealthAI](ActionBehaviors/StealthAI.md)|Gives the ability of the NPCControl to spot the player if it enters its field of vision (represented by 2 trigger colliders) which has the effect of triggering an [event](../../../Enums%20and%20IDs/Events.md). The event id and the wideness of the field of vision are configurable as well as an option to set the entity.[animstate](../../EntityControl/Animations/animstate.md) to `Sleep` at the start of the DoBehavior cycle.|
|
||||
|27|[SetPathJump](ActionBehaviors/SetPathJump.md)|Similar than [SetPath](SetPath.md), but after the [MoveTowards](../../EntityControl/EntityControl%20Methods.md#movetowards) call, the entity `forcejump` is set to true which makes it jump during its FixedUpdate when moving to the next node if possible.|
|
||||
|28|[DisguiseOnceJumpForward](ActionBehaviors/DisguiseOnceJumpForward.md)|UNUSED, A semi functional and likely unfinished behavior similar to [Disguise](Disguise.md) that is recognised as a disguise behavior alongside [Disguise](Disguise.md) and [DisguiseOnce](DisguiseOnce.md), but it doesn't have any DoBehavior logic.|
|
||||
|29|[ChangeSpriteInRandius](ActionBehaviors/ChangeSpriteInRandius.md)|When the player is present, the entity.[animstate](../../EntityControl/Animations/animstate.md) is set to `actionfrequency[0]` when the distance between this and the player is less than the `wanderradius`, it is set to `actionfrequency[1]` otherwise.|
|
||||
|30|[ChaseWhenAnim](ActionBehaviors/ChaseWhenAnim.md)|Perform the same logic than [ChasePlayer](ChasePlayer.md) when the entity.[animstate](../../EntityControl/Animations/animstate.md) is `Chase`. Otherwise, if the entity.`animstate` isn't the frequency, entity.`animstate` is set to it with a 20.0 frames `behaviorcooldown` (prevents a [WalkWhenAnim](WalkWhenAnim.md) doing a [Wander](Wander.md) DoBehavior cycle to process for 20.0 frames when entity.`animstate` is `Idle`) and a [StopForceMove](../../EntityControl/EntityControl%20Methods.md) call on the entity.|
|
||||
|31|[WalkWhenAnim](ActionBehaviors/WalkWhenAnim.md)|Perform [Wander](Wander.md) when the entity [animstate](../../EntityControl/Animations/animstate.md) is `Walk` (or `Idle` if the `behaviorcooldown` expired) or change it to the frequency when it's not with a `behaviorcooldown` of 20.0 frames (prevents another [Wander](Wander.md) cycle to process for 20.0 frames when entity.`animstate` is `Idle`).|
|
||||
|32|[WanderOffscreen](ActionBehaviors/WanderOffscreen.md)|The same than [Wander](Wander.md), but movements are allowed when inactive or paused.|
|
||||
|33|[WanderNoWarp](ActionBehaviors/WanderNoWarp.md)|The same than [Wander](Wander.md), but the warp branch logic is disabled. This means even if `maxtries` reaches 20 or that the distance between this position and the entity.`startpos` gets higher than `radiuslimit`, the entity will not warp and continue as normal.|
|
||||
|34|[WanderOnWater](ActionBehaviors/WanderOnWater.md)|The same than [WanderNoWarp](WanderNoWarp.md), but the y position is adjusted according to the map.`waterfloat` if one exists.|
|
||||
|35|[ChaseOnWater](ActionBehaviors/ChaseOnWater.md)|The same than [ChasePlayer](ChasePlayer.md), but the y position is adjusted according to the map.`waterfloat` if one exists.|
|
||||
|16|[SetPath](ActionBehaviors/SetPath.md)|Periodically performs [MoveTowards](../EntityControl/EntityControl%20Methods.md#movetowards) calls on the entity using a fixed configurable interval between moves and the path being made of position nodes defined in `vectordata`.|
|
||||
|17|[ChargeAtPlayer](ActionBehaviors/ChargeAtPlayer.md)|Charges at the player with `attacking` set to true during the movement towards the player (this will allow an [Enemy](Enemy.md) to initiate a battle with the advantage if it collides with the player and all conditions are met to start a battle with the advantage).|
|
||||
|18|[ChargeAtPlayerFlipSprite](ActionBehaviors/ChargeAtPlayerFlipSprite.md)|The same then `ChargeAtPlayer`, but right after the [MoveTowards](../EntityControl/EntityControl%20Methods.md#movetowards) call on the entity, the entity.`sprite` has its angles set to (0.0, the y angles facing the player + 90.0, 0.0) with an `overrideonlyflip` which locks the entity.`sprite` facing direction until the charge part of the coroutine is over.|
|
||||
|19|[ShootProjectile](ActionBehaviors/ShootProjectile.md)|Attacks the player by shooting an OverworldProjectile which can, under the right conditions, start a battle with advantage. The specifics of the projectile logic is dependant on the [animid](../../Enums%20and%20IDs/AnimIDs.md) and only a few have a logic defined for this behavior.|
|
||||
|20|[ShootProjectilePredict](ActionBehaviors/ShootProjectilePredict.md)|UNUSED, An alias of `ShootProjectile`.|
|
||||
|21|[ChargeAndAttack](ActionBehaviors/ChargeAndAttack.md)|The same than `ChasePlayer`, but also attacks the player (with `attacking` set to true during the attack) where the actions depends on the [AnimID](../../Enums%20and%20IDs/AnimIDs.md) when getting closer than a configurable threshold. Only a few animIds have an attack logic defined for this behavior.|
|
||||
|22|[AlwaysWander](ActionBehaviors/AlwaysWander.md)|UNUSED, A very cut down version of `wander` where the entity will always, when it can, move somewhere on the next DoBehavior cycle even if it is in the process of moving already.|
|
||||
|23|[Unmoveable](ActionBehaviors/Unmoveable.md)|Prevents an [Enemy](Enemy.md) with this behavior (either default or `inrange`) to not move during the [Dizzy](Notable%20methods/Dizzy.md) process. This doesn't have any logic, its presence is what affects the NPCControl.|
|
||||
|24|[ChargeAttackUnderground](ActionBehaviors/ChargeAttackUnderground.md)|The same than `ChargeAndAttack`, but the behavior always makes the entity `digging` when not attacking and it can only attack after 30.0 frames of `digtime`.|
|
||||
|25|[WanderUnderground](ActionBehaviors/WanderUnderground.md)|The same than `Wander`, but the entity immediately starts digging underground before actually wandering.|
|
||||
|26|[StealthAI](ActionBehaviors/StealthAI.md)|Gives the ability of the NPCControl to spot the player if it enters its field of vision (represented by 2 trigger colliders) which has the effect of triggering an [event](../../Enums%20and%20IDs/Events.md). The event id and the wideness of the field of vision are configurable as well as an option to set the entity.[animstate](../EntityControl/Animations/animstate.md) to `Sleep` at the start of the DoBehavior cycle.|
|
||||
|27|[SetPathJump](ActionBehaviors/SetPathJump.md)|Similar than `SetPath`, but after the [MoveTowards](../EntityControl/EntityControl%20Methods.md#movetowards) call, the entity `forcejump` is set to true which makes it jump during its FixedUpdate when moving to the next node if possible.|
|
||||
|28|[DisguiseOnceJumpForward](ActionBehaviors/DisguiseOnceJumpForward.md)|UNUSED, A semi functional and likely unfinished behavior similar to `Disguise` that is recognised as a disguise behavior alongside `Disguise` and `DisguiseOnce`, but it doesn't have any DoBehavior logic.|
|
||||
|29|[ChangeSpriteInRandius](ActionBehaviors/ChangeSpriteInRandius.md)|When the player is present, the entity.[animstate](../EntityControl/Animations/animstate.md) is set to `actionfrequency[0]` when the distance between this and the player is less than the `wanderradius`, it is set to `actionfrequency[1]` otherwise.|
|
||||
|30|[ChaseWhenAnim](ActionBehaviors/ChaseWhenAnim.md)|Perform the same logic than `ChasePlayer` when the entity.[animstate](../EntityControl/Animations/animstate.md) is `Chase`. Otherwise, if the entity.`animstate` isn't the frequency, entity.`animstate` is set to it with a 20.0 frames `behaviorcooldown` (prevents a `WalkWhenAnim` doing a `Wander` DoBehavior cycle to process for 20.0 frames when entity.`animstate` is `Idle`) and a [StopForceMove](../EntityControl/EntityControl%20Methods.md) call on the entity.|
|
||||
|31|[WalkWhenAnim](ActionBehaviors/WalkWhenAnim.md)|Perform `Wander` when the entity [animstate](../EntityControl/Animations/animstate.md) is `Walk` (or `Idle` if the `behaviorcooldown` expired) or change it to the frequency when it's not with a `behaviorcooldown` of 20.0 frames (prevents another `Wander` cycle to process for 20.0 frames when entity.`animstate` is `Idle`).|
|
||||
|32|[WanderOffscreen](ActionBehaviors/WanderOffscreen.md)|The same than `Wander`, but movements are allowed when inactive or paused.|
|
||||
|33|[WanderNoWarp](ActionBehaviors/WanderNoWarp.md)|The same than `Wander`, but the warp branch logic is disabled. This means even if `maxtries` reaches 20 or that the distance between this position and the entity.`startpos` gets higher than `radiuslimit`, the entity will not warp and continue as normal.|
|
||||
|34|[WanderOnWater](ActionBehaviors/WanderOnWater.md)|The same than `WanderNoWarp`, but the y position is adjusted according to the map.`waterfloat` if one exists.|
|
||||
|35|[ChaseOnWater](ActionBehaviors/ChaseOnWater.md)|The same than `ChasePlayer`, but the y position is adjusted according to the map.`waterfloat` if one exists.|
|
||||
@@ -22,6 +22,7 @@ This has the implications that the NPCControl will always wander if all of the c
|
||||
If they aren't in a `movemove`, the player needs to not be `tattling` while we aren't in a `pause` to wander on this cycle.
|
||||
|
||||
If they are in a `forcemove`, the above applies on top of all of the following needing to be true:
|
||||
|
||||
- entity.`hitwall` is false
|
||||
- entity.`onground` is true
|
||||
- entity.`detect` is absent or [HasGroundAhead](../../EntityControl/EntityControl%20Methods.md#hasgroundahead) from the entity.`forcetarget` returns true
|
||||
|
||||
@@ -35,10 +35,10 @@ These are the different attacks an NPCControl can do with this behavior, but onl
|
||||
- 0.1 seconds are yielded
|
||||
- All frames are yielded as long as we are in a `pause`, `minipause`, `inevent` or we are in a `battle` that is `inevent`
|
||||
- If the distance between the NPCControl and the player is less than 2.0:
|
||||
- NPCControl.[StartBattle](../Notable%20methods/StartBattle.md) is called
|
||||
- entity.`overrideanim` is set to false
|
||||
- [StopForceBehavior](../Notable%20methods/StopForceBehavior.md) is called
|
||||
- The coroutine ends early with a yield break
|
||||
- NPCControl.[StartBattle](../Notable%20methods/StartBattle.md) is called
|
||||
- entity.`overrideanim` is set to false
|
||||
- [StopForceBehavior](../Notable%20methods/StopForceBehavior.md) is called
|
||||
- The coroutine ends early with a yield break
|
||||
- Otherwise, 0.5 seconds are yielded
|
||||
- entity.`animstate` is set to 0 (`Idle`)
|
||||
|
||||
@@ -58,23 +58,23 @@ The same than `LeafbugClubber`, but with the difference that instead of the `Tos
|
||||
- `dirtcd` is set to 30.0
|
||||
- [FlipSpriteAngleAt](../../EntityControl/EntityControl%20Methods.md#flipspriteangleat) is called on the entity with the player at the position and (0.0, 90.0, 0.0) as the offset
|
||||
- From there, there is a loop that goes on for up to 40.0 frames, but counted by a local variable which only gets incremented towards the end of the loop by the game's frametime (meaning there may be more frames yielded during the loop, but it will stop after 40.0 frames are counted using the local variable):
|
||||
- The position is set to be on a quadratic Bezier curve with the following:
|
||||
- The start is the NPCControl position before this attack started
|
||||
- The end is where the player is, but undershot by 1.5 from the direction of the NPCControl. This point is limited to be in a radius where the center is entity.`startpos` and the radius being `radiuslimit`
|
||||
- The y of the midpoint is 4.0
|
||||
- The t factor is the ratio of the current amount of frames ellpsed since the start of the loop over 40.0. This essentially means the curve will last for a total of 40.0 counted frames and each position is interpolated over the course of those 40.0 frames
|
||||
- `attacking` is set to true
|
||||
- If the distance between the player and this NPCControl is less than 1.5 and we aren't in a `minipause`:
|
||||
- NPCControl.[StartBattle](../Notable%20methods/StartBattle.md) is called
|
||||
- entity.`overrideanim` is set to false
|
||||
- [StopForceBehavior](../Notable%20methods/StopForceBehavior.md) is called
|
||||
- entity.`overrideflip` is set to false
|
||||
- This coroutines ends early with a yield break
|
||||
- [DetectDirection](../../EntityControl/EntityControl%20Methods.md#detectdirection) is called with the NPCControl position - the normalised direction from the player to this NPCControl
|
||||
- If entity.`hitwall` the loop is exited early (but the coroutine still continues). Essentially, it prevents movement when the entity.`detect` goes off
|
||||
- Otherwise, a frame is yielded
|
||||
- This is where the local variable controling this loop is incremented by the game's frametime. Only this increment counts (no other yields counts)
|
||||
- All frames are yielded as long as we are in a `pause`, `minipause`, `inevent` or we are in a `battle` that is `inevent`
|
||||
- The position is set to be on a quadratic Bezier curve with the following:
|
||||
- The start is the NPCControl position before this attack started
|
||||
- The end is where the player is, but undershot by 1.5 from the direction of the NPCControl. This point is limited to be in a radius where the center is entity.`startpos` and the radius being `radiuslimit`
|
||||
- The y of the midpoint is 4.0
|
||||
- The t factor is the ratio of the current amount of frames ellpsed since the start of the loop over 40.0. This essentially means the curve will last for a total of 40.0 counted frames and each position is interpolated over the course of those 40.0 frames
|
||||
- `attacking` is set to true
|
||||
- If the distance between the player and this NPCControl is less than 1.5 and we aren't in a `minipause`:
|
||||
- NPCControl.[StartBattle](../Notable%20methods/StartBattle.md) is called
|
||||
- entity.`overrideanim` is set to false
|
||||
- [StopForceBehavior](../Notable%20methods/StopForceBehavior.md) is called
|
||||
- entity.`overrideflip` is set to false
|
||||
- This coroutines ends early with a yield break
|
||||
- [DetectDirection](../../EntityControl/EntityControl%20Methods.md#detectdirection) is called with the NPCControl position - the normalised direction from the player to this NPCControl
|
||||
- If entity.`hitwall` the loop is exited early (but the coroutine still continues). Essentially, it prevents movement when the entity.`detect` goes off
|
||||
- Otherwise, a frame is yielded
|
||||
- This is where the local variable controling this loop is incremented by the game's frametime. Only this increment counts (no other yields counts)
|
||||
- All frames are yielded as long as we are in a `pause`, `minipause`, `inevent` or we are in a `battle` that is `inevent`
|
||||
- When the loop is done, if `dirtcd` expired, `DirtExplodeLight` are played at the NPCControl position for 1 seconds with 0.75 uniform scaling
|
||||
- `dirtcd` is set to 30.0
|
||||
- entity.`overrideflip` is set to false
|
||||
|
||||
@@ -26,10 +26,10 @@ This is a private coroutine specific to this behavior. It receives the behavior
|
||||
- entity.`detect` is ensured to be created
|
||||
- [DetectDirection](../../EntityControl/EntityControl%20Methods.md#detectdirection) is called on the entity using the player position
|
||||
- As long as the entity.`forcemove` is ongoing and the entity.`hitwall` is false:
|
||||
- entity.`emoticonid` is set to 2 (the red !)
|
||||
- entity.`emoticoncolldown` is set to 5.0
|
||||
- If entity.`initialheight` is above 0.1, entity.`height` is set to a lerp from entity.`initialheight` to 0.25 with a factor of (the x/z square distance between this NPCControl and entity.`forcetarget`) / (the x/z square distance between entity.`startpos` and entity.`forcetarget`). NOTE: the math is likely incorrect, but the main point here is the NPCControl lowers faster as the player is further away from it and slows down as it gets closer
|
||||
- A frame is yieled
|
||||
- entity.`emoticonid` is set to 2 (the red !)
|
||||
- entity.`emoticoncolldown` is set to 5.0
|
||||
- If entity.`initialheight` is above 0.1, entity.`height` is set to a lerp from entity.`initialheight` to 0.25 with a factor of (the x/z square distance between this NPCControl and entity.`forcetarget`) / (the x/z square distance between entity.`startpos` and entity.`forcetarget`). NOTE: the math is likely incorrect, but the main point here is the NPCControl lowers faster as the player is further away from it and slows down as it gets closer
|
||||
- A frame is yieled
|
||||
- A frame is yieled
|
||||
- entity.`sprite` angles are set to the return of a FlipAngle call on the entity
|
||||
- `attacking` is set to false
|
||||
|
||||
@@ -19,4 +19,4 @@ None, overriden to 2.0 if it's not between 0.0 and 10.0 inclusive.
|
||||
- The position is limited to a radius of `radiuslimit` where the center is `startpos` ignoring the y component
|
||||
|
||||
## Update (Common end logic)
|
||||
If this is the current behavior (according to `inrange`) and we are in `minipause` or `inevent`, then [StopForceMove](../EntityControl/EntityControl%20Methods.md#StopForceMove) is called on the entity.
|
||||
If this is the current behavior (according to `inrange`) and we are in `minipause` or `inevent`, then [StopForceMove](../../EntityControl/EntityControl%20Methods.md#stopforcemove) is called on the entity.
|
||||
|
||||
@@ -13,6 +13,7 @@ It can be used as the `inrange` behavior while [WalkWhenAnim](WalkWhenAnim.md) i
|
||||
If the entity.`animstate` is `Chase`, this acts as an alias to [ChasePlayer](ChasePlayer.md).
|
||||
|
||||
Otherwise, if the current entity.`animstate` isn't the `frequency`:
|
||||
|
||||
- The `behaviorcooldown` is set to 20.0 (prevents a [WalkWhenAnim](WalkWhenAnim.md) doing a [Wander](Wander.md) DoBehavior cycle to process for 20.0 frames when entity.`animstate` is `Idle`)
|
||||
- [StopForceMove](../../EntityControl/EntityControl%20Methods.md#StopForceMove) is called on the entity
|
||||
- The entity.`animstate` is set to frequency
|
||||
|
||||
@@ -19,14 +19,16 @@ Due to this complex management of the `disguiseobj`, this behavior's logic is ve
|
||||
|
||||
## Start / SetUp
|
||||
On SetUp:
|
||||
|
||||
- entity.`alwaysactive` is set to true
|
||||
- `disguiseobj` is initialised to the transform of `prefabs/Disguises/x` prefab where x is the entity.[AnimID](../../Enums%20and%20IDs/AnimIDs.md). It gets childed to the entity.`sprite` which also gets disabled making only the disguise visible instead of the sprite. The local position is ensured to be Vector3.zero, but the angles and the scales depends on the AnimID (anything not mentioned is left default):
|
||||
- `Cactus`: scale of (70.0, 25.0, 70.0)
|
||||
- `Mushroom`: scale of (20.0, 15.0, 25.0)
|
||||
- `CursedSkull`: scale of 0.5 uniform, local position of (0.0, 0.0, -0.5) and angles of (-90.0, 0.0, 0.0)
|
||||
- `Plumpling`: scale of 0.2 uniform and angles of (-90.0, 0.0, 180.0)
|
||||
- `disguiseobj` is initialised to the transform of `prefabs/Disguises/x` prefab where x is the entity.[AnimID](../../../Enums%20and%20IDs/AnimIDs.md). It gets childed to the entity.`sprite` which also gets disabled making only the disguise visible instead of the sprite. The local position is ensured to be Vector3.zero, but the angles and the scales depends on the AnimID (anything not mentioned is left default):
|
||||
- `Cactus`: scale of (70.0, 25.0, 70.0)
|
||||
- `Mushroom`: scale of (20.0, 15.0, 25.0)
|
||||
- `CursedSkull`: scale of 0.5 uniform, local position of (0.0, 0.0, -0.5) and angles of (-90.0, 0.0, 0.0)
|
||||
- `Plumpling`: scale of 0.2 uniform and angles of (-90.0, 0.0, 180.0)
|
||||
|
||||
After SetUp returned on Start:
|
||||
|
||||
- `disguiseobj` is enabled
|
||||
- `disguisecooldown` is set to -1 (meaning it simulates an already expired disguise cooldown)
|
||||
- entity.`sprite` is disabled
|
||||
@@ -56,12 +58,13 @@ The main logic depends on the `disguisecooldown` which is an int countdown of th
|
||||
- The entity.[animstate](../../EntityControl/Animations/animstate.md) is set to the entity.`walkstate`
|
||||
- The entity.`oldstate` is set to -1 (which forces a sprite update)
|
||||
- If entity.`hitwall` is true:
|
||||
- The NPCControl position is set to entity.`startpos`
|
||||
- entity.`rigid` velocity is zeroed out
|
||||
- DeathSmoke particles are played at the NPCControl position if the entity is `incamera`
|
||||
- The NPCControl position is set to entity.`startpos`
|
||||
- entity.`rigid` velocity is zeroed out
|
||||
- DeathSmoke particles are played at the NPCControl position if the entity is `incamera`
|
||||
|
||||
## Update (Inactive)
|
||||
If the `disguisecooldown` is fully expired (it's -1):
|
||||
|
||||
- `disguiseobj` is enabled
|
||||
- The entity.`sprite` gets disabled if entity.`campos` z is above 5.0 (meaning it's too far forward from the camera), it remains enabled otherwise
|
||||
- `overrideminheight` is set to true
|
||||
@@ -91,6 +94,7 @@ This update method is disallowed to change the `sprite` enablement on an [Enemy]
|
||||
|
||||
## MainManager.RefreshEntities
|
||||
This logic only matters if the method was called as a result of MapControl.Start, MapControl.RefreshInsides and BattleControl.ReturnToOverworld:
|
||||
|
||||
- `disguisecooldown` is set to -1 (fully expired)
|
||||
- `disguiseobj` is disabled
|
||||
- entity.`sprite` being enabled.
|
||||
@@ -109,6 +113,7 @@ This will get further handled by DoBehavior, see the section below for details
|
||||
|
||||
## DoBehavior (behavior no longer exists)
|
||||
A special case is handled where this behavior no longer exists, but the `disguiseobj` still does. The only way for this case to happen is if a destroy of the `disguiseobj` was requested by [RespawnEnemy](../Notable%20methods/RespawnEnemy.md) because not only it destroys it, but it also changes the default behavior to [Wander](Wander.md). If this was the previous one and it wasn't the `inrange` one, then it no longer exists after the respawn which makes it fall into this special case. The handling goes as follow:
|
||||
|
||||
- TempSpin is called on the entity which sets its `spin` to (0.0, 20.0, 0.0) and then zerored out in 0.2 seconds
|
||||
- The `disguisecooldown` is set to 120.0
|
||||
- The entity.`overridehright` is set to false
|
||||
|
||||
@@ -14,6 +14,7 @@ The entity.`alwaysactive` is set to true.
|
||||
If `returntoheight` is true entity.`height` is set to a lerp from the existing one to entity.`initialheight` with a factor of 0.1.
|
||||
|
||||
What happens next depends if all of the following are true:
|
||||
|
||||
- The entity isn't in a `forcemove`
|
||||
- The entity `hitwall` is false
|
||||
- `vectordata` exists and isn't empty
|
||||
@@ -32,7 +33,7 @@ If it has expired, then [MoveTowards](../../EntityControl/EntityControl%20Method
|
||||
Finally, `actioncooldown` is set to the frequency and the cycle continues.
|
||||
|
||||
## Update (Inactive, every 3 frames)
|
||||
Normally, when the entity is in a [forcemove](../EntityControl/EntityControl%20Methods.md#forcemove), [StopForceMove](../EntityControl/EntityControl%20Methods.md#StopForceMove) is called on it, but this behavior is an exception to this where it will not be called here.
|
||||
Normally, when the entity is in a `forcemove`, [StopForceMove](../../EntityControl/EntityControl%20Methods.md#stopforcemove) is called on it, but this behavior is an exception to this where it will not be called here.
|
||||
|
||||
## EntityControl.[Death](../../EntityControl/Notable%20methods/Death.md)
|
||||
This behavior forbids an [Enemy](../NPCType.md#enemy) with it to drop an item because the behavior uses `vectordata` for its own purposes which interferes with the enemy item drop system.
|
||||
|
||||
@@ -8,6 +8,7 @@ None.
|
||||
This component is only involved over the course of this behavior. It is meant to be created externally via a static method called NewProjectile defined in that component's MonoBehavior. It takes a lot of parameters to setup the projectile notably a `parent` which will be this NPCControl.
|
||||
|
||||
At a basic level, an OverworldProjectile is a sprite with a default trigger BoxCollider that has the ability to call NPCControl.[StartBattle](../Notable%20methods/StartBattle.md) with advantage on its OnTriggerStay when all of the following conditions are fufilled:
|
||||
|
||||
- The other collider is the player
|
||||
- We aren't in a `pause`, `minipause`, `inevent` or `inbattle`
|
||||
- The player isn't on `shield`
|
||||
@@ -21,6 +22,7 @@ As for the movement of the OverworldProjectile, it moves along a beizer curve wi
|
||||
As for the rendering of of the projectile, it's a sprite index of the `Sprites/Misc/projectiles` sprites, but it's possible to send a negative number to specify an [item](../../../Enums%20and%20IDs/Items.md) id (the absolute value) to use as the sprite.
|
||||
|
||||
Notable traits of an OverworldProjectile GameObject:
|
||||
|
||||
- Its name is `proj`
|
||||
- It is childed to the map
|
||||
- A GameObject is childed to it with a SpriteRenderer called `tempproj`
|
||||
@@ -42,11 +44,11 @@ This is a private coroutine specific to this behavior. It receives the behavior
|
||||
- All null elements in `projectiles` are removed
|
||||
- [FaceTowards](../../EntityControl/EntityControl%20Methods.md#facetowards) is called on the entity to face the player
|
||||
- From there, the projectile is fired depending on the entity.[animid](../../../Enums%20and%20IDs/AnimIDs.md#animids). See the section below for more details. If this is not an animid with a projectile logic, the following is done:
|
||||
- entity.[animstate](../../EntityControl/Animations/animstate.md) is set to entity.`basestate`
|
||||
- If we aren't `inrange`, entity.`overrideonlyflip` is set to false
|
||||
- A frame is yielded
|
||||
- [StopForceBehavior](../Notable%20methods/StopForceBehavior.md) is called
|
||||
- The coroutine is exited early with a yield break
|
||||
- entity.[animstate](../../EntityControl/Animations/animstate.md) is set to entity.`basestate`
|
||||
- If we aren't `inrange`, entity.`overrideonlyflip` is set to false
|
||||
- A frame is yielded
|
||||
- [StopForceBehavior](../Notable%20methods/StopForceBehavior.md) is called
|
||||
- The coroutine is exited early with a yield break
|
||||
- entity.[animstate](../../EntityControl/Animations/animstate.md) is set to entity.`basestate`
|
||||
- If we aren't `inrange`, entity.`overrideonlyflip` is set to false
|
||||
- A frame is yielded
|
||||
@@ -58,6 +60,7 @@ Here are the different logic available for each [animid](../../../Enums%20and%20
|
||||
|
||||
#### `DeadLanderA`
|
||||
If there's no `projectiles`:
|
||||
|
||||
- entity.[animstate](../../EntityControl/Animations/animstate.md) is set to 103 (shooting)
|
||||
- A second is yielded
|
||||
- All frames are yielded as long as we are in a `pause`, `minipause`, `inevent` or we are in a `battle` that is `inevent`
|
||||
@@ -65,34 +68,35 @@ If there's no `projectiles`:
|
||||
- [FaceTowards](../../EntityControl/EntityControl%20Methods.md#facetowards) is called on the entity to face the player
|
||||
- entity.`animstate` is set to 104 (going back to idle from shooting)
|
||||
- A projectile gets added with this NPCControl as the parent:
|
||||
- sprite index 10 (honey projectile)
|
||||
- starting position at this NPCControl position - its right vector + (0.0, 1.25, 0.0)
|
||||
- target position being the player position undershot by 1.5 towards the direction of the player
|
||||
- No spin
|
||||
- y angles of the entity.`sprite` angle, but no x or z
|
||||
- size of uniform 0.75
|
||||
- `HoneyExplode` particles on the projectle destruction
|
||||
- y midpoint of the bezier curve of 2.0
|
||||
- time of 50.0 frames
|
||||
- shadow size multiplier of 0.25
|
||||
- sprite index 10 (honey projectile)
|
||||
- starting position at this NPCControl position - its right vector + (0.0, 1.25, 0.0)
|
||||
- target position being the player position undershot by 1.5 towards the direction of the player
|
||||
- No spin
|
||||
- y angles of the entity.`sprite` angle, but no x or z
|
||||
- size of uniform 0.75
|
||||
- `HoneyExplode` particles on the projectle destruction
|
||||
- y midpoint of the bezier curve of 2.0
|
||||
- time of 50.0 frames
|
||||
- shadow size multiplier of 0.25
|
||||
- 0.5 seconds are yielded
|
||||
|
||||
No matter if there was projectiles or not, all frames are yielded as long as we are in a `pause`, `minipause`, `inevent` or we are in a `battle` that is `inevent` followed by an additional yield which ends this projectile.
|
||||
|
||||
#### `WaspBomber`
|
||||
If there's no `projectiles`:
|
||||
|
||||
- entity.`animstate` is set to 101 (throwing)
|
||||
- A projectile gets added with this NPCControl as the parent:
|
||||
- sprite index -30 (`SpicyBomb` [item](../../../Enums%20and%20IDs/Items.md) sprite)
|
||||
- starting position at this NPCControl position - its right vector + (0.25, 1.25, -0.1)
|
||||
- target position being the player position undershot by 1.5 towards the direction of the player
|
||||
- Spin of 20.0 in z (no x or y)
|
||||
- y angles of the entity.`sprite` angle, but no x or z
|
||||
- size of uniform 1.0
|
||||
- `explosionsmall` particles on the projectle destruction (also, if the player is less than 15.0 away on destruction, `Explosion` sound is played at 0.75 pitch followed by a ShakeScreen of 0.1 for 0.5 seconds without reset)
|
||||
- y midpoint of the bezier curve of 5.0
|
||||
- time of 80.0 frames
|
||||
- shadow size multiplier of 0.5
|
||||
- sprite index -30 (`SpicyBomb` [item](../../../Enums%20and%20IDs/Items.md) sprite)
|
||||
- starting position at this NPCControl position - its right vector + (0.25, 1.25, -0.1)
|
||||
- target position being the player position undershot by 1.5 towards the direction of the player
|
||||
- Spin of 20.0 in z (no x or y)
|
||||
- y angles of the entity.`sprite` angle, but no x or z
|
||||
- size of uniform 1.0
|
||||
- `explosionsmall` particles on the projectle destruction (also, if the player is less than 15.0 away on destruction, `Explosion` sound is played at 0.75 pitch followed by a ShakeScreen of 0.1 for 0.5 seconds without reset)
|
||||
- y midpoint of the bezier curve of 5.0
|
||||
- time of 80.0 frames
|
||||
- shadow size multiplier of 0.5
|
||||
- a second is yielded
|
||||
- entity.`animstate` is set to 0 (`Idle`)
|
||||
|
||||
@@ -102,6 +106,7 @@ No matter if there was projectiles or not, all frames are yielded as long as we
|
||||
If there was at least 1 `projectiles`, all frames are yielded as long as we are in a `pause`, `minipause`, `inevent` or we are in a `battle` that is `inevent` followed by an additional yield which ends this projectile logic.
|
||||
|
||||
If there's no `projectiles`:
|
||||
|
||||
- entity.`animstate` is set to 100 (lowering upper limbs to the ground)
|
||||
- 0.5 seconds are yielded
|
||||
- entity.`animstate` is set to 101 (putting upper limbs in the air)
|
||||
@@ -111,10 +116,10 @@ If there's no `projectiles`:
|
||||
- `internaltransform[0]` is childed to the map
|
||||
- If `dizzytime` or `freezecooldown` aren't expired, this projectile logic ends early, but the coroutine still continues
|
||||
- From there, there is a loop that goes on for up to 11.0 frames, but counted by a local variable which only gets incremented towards the end of the loop by the game's frametime (meaning there may be more frames yielded during the loop, but it will stop after 11.0 frames are counted using the local variable):
|
||||
- `internaltransform[0]` position is set to a lerp from the existing one to (entity.`sprite` position + the normalised right vector of the entity + 0.3 in y) with a factor of the ratio of the amount of frames counted in this loop over 11.0. This basically moves the rock on a straight line to a position above the entity, but slightly towards them
|
||||
- If `dizzytime` or `freezecooldown` aren't expired, this projectile logic ends early, but before it is ends, all frames are yielded as long as we are in a `pause`, `minipause`, `inevent` or we are in a `battle` that is `inevent` followed by an additional yield
|
||||
- This is where the local frame counter is incremented by the game's frametime, but only if we aren't in a `pause`
|
||||
- A frame is yielded
|
||||
- `internaltransform[0]` position is set to a lerp from the existing one to (entity.`sprite` position + the normalised right vector of the entity + 0.3 in y) with a factor of the ratio of the amount of frames counted in this loop over 11.0. This basically moves the rock on a straight line to a position above the entity, but slightly towards them
|
||||
- If `dizzytime` or `freezecooldown` aren't expired, this projectile logic ends early, but before it is ends, all frames are yielded as long as we are in a `pause`, `minipause`, `inevent` or we are in a `battle` that is `inevent` followed by an additional yield
|
||||
- This is where the local frame counter is incremented by the game's frametime, but only if we aren't in a `pause`
|
||||
- A frame is yielded
|
||||
- 0.25 seconds are yielded
|
||||
- All frames are yielded as long as the player isn't free (ignoring flying)
|
||||
- entity.`animstate` is set to 28 (TossItem)
|
||||
@@ -122,16 +127,16 @@ If there's no `projectiles`:
|
||||
- If `dizzytime` or `freezecooldown` aren't expired, this projectile logic ends early, but the coroutine still continues
|
||||
- The `Toss3` sound is played at 0.9 volume
|
||||
- A projectile gets added with this NPCControl as the parent:
|
||||
- sprite index 17 (A brown missile)
|
||||
- starting position at this `internaltransform[0]` position
|
||||
- target position being the player position undershot by 1.5 towards the direction of the player
|
||||
- No spin
|
||||
- y angles of the entity.`sprite` angle and z angle of 90.0, no x
|
||||
- size of uniform 0.5
|
||||
- `Rock` particles on the projectle destruction (will also lead to the rooting of the rock if it still exists followed by CrackRock being called on it. Additionally, if the player is 15.0 away, `RockBreak` sound is played at 0.75 pitch followed by a ShakeScreen of 0.1 for 0.5 seconds without reset)
|
||||
- y midpoint of the bezier curve of 3.0
|
||||
- time of 40.0 frames
|
||||
- shadow size multiplier of 0.25
|
||||
- sprite index 17 (A brown missile)
|
||||
- starting position at this `internaltransform[0]` position
|
||||
- target position being the player position undershot by 1.5 towards the direction of the player
|
||||
- No spin
|
||||
- y angles of the entity.`sprite` angle and z angle of 90.0, no x
|
||||
- size of uniform 0.5
|
||||
- `Rock` particles on the projectle destruction (will also lead to the rooting of the rock if it still exists followed by CrackRock being called on it. Additionally, if the player is 15.0 away, `RockBreak` sound is played at 0.75 pitch followed by a ShakeScreen of 0.1 for 0.5 seconds without reset)
|
||||
- y midpoint of the bezier curve of 3.0
|
||||
- time of 40.0 frames
|
||||
- shadow size multiplier of 0.25
|
||||
- The projectile gets childed to `internaltransform[0]`. This is done so because the game hides the fact the rock isn't the projectile, but rather a brown missile is and its sprite gets disabled on the OverworldProjectile's Start because of the `Rock` particle on death parameter sent
|
||||
- `internaltransform[0]` is set to null (OverworldProjectile takes control of it from now on)
|
||||
- 0.5 seconds are yielded
|
||||
@@ -139,6 +144,7 @@ If there's no `projectiles`:
|
||||
|
||||
#### `SneilEnemy`
|
||||
If there's no `projectiles`:
|
||||
|
||||
- entity.`animstate` is set to 100 (preparing to shoot)
|
||||
- [FlipSpriteAngleAt](../../EntityControl/EntityControl%20Methods.md#flipspriteangleat) is called on the entity towards the player with offset (0.0, 90.0, 0.0)
|
||||
- All frames are yielded as long as we are in a `pause`, `minipause`, `inevent` or we are in a `battle` that is `inevent`
|
||||
@@ -146,20 +152,21 @@ If there's no `projectiles`:
|
||||
- The `Lazer` sound is played on the entity
|
||||
- [FlipSpriteAngleAt](../../EntityControl/EntityControl%20Methods.md#flipspriteangleat) is called on the entity towards the player with offset (0.0, 90.0, 0.0)
|
||||
- A projectile gets added with this NPCControl as the parent:
|
||||
- sprite index 4 (A white lightning bolt)
|
||||
- starting position at this NPCControl position - its right vector + 0.1 in y
|
||||
- target position being the player position undershot by 1.5 towards the direction of the player + 2.0 in y
|
||||
- No spin
|
||||
- y angles of the entity.`sprite` angle and z angle of 90.0, no x
|
||||
- size of uniform 0.75
|
||||
- No particles on destruction
|
||||
- y midpoint of the bezier curve of 0.0
|
||||
- time of 60.0 frames
|
||||
- shadow size multiplier of 0.25
|
||||
- sprite index 4 (A white lightning bolt)
|
||||
- starting position at this NPCControl position - its right vector + 0.1 in y
|
||||
- target position being the player position undershot by 1.5 towards the direction of the player + 2.0 in y
|
||||
- No spin
|
||||
- y angles of the entity.`sprite` angle and z angle of 90.0, no x
|
||||
- size of uniform 0.75
|
||||
- No particles on destruction
|
||||
- y midpoint of the bezier curve of 0.0
|
||||
- time of 60.0 frames
|
||||
- shadow size multiplier of 0.25
|
||||
- 0.75 seconds are yielded
|
||||
- all frames are yielded as long as we are in a `pause`, `minipause`, `inevent` or we are in a `battle` that is `inevent` followed by an additional yield which ends this projectile.
|
||||
|
||||
Otherwise, if there was a projectile:
|
||||
|
||||
- entity.`animstate` is set to entity.`basestate`
|
||||
- entity.`overrideflip` is set to false
|
||||
- A frame is yielded
|
||||
@@ -168,6 +175,7 @@ Otherwise, if there was a projectile:
|
||||
|
||||
#### `BeeBot`
|
||||
If there's less than 2 `projectiles`:
|
||||
|
||||
- entity.`animstate` is set to 100 (preparing to shoot)
|
||||
- [FlipSpriteAngleAt](../../EntityControl/EntityControl%20Methods.md#flipspriteangleat) is called on the entity towards the player with offset (0.0, 90.0, 0.0)
|
||||
- 0.5 seconds are yielded
|
||||
@@ -175,28 +183,30 @@ If there's less than 2 `projectiles`:
|
||||
- If `dizzytime` or `freezecooldown` aren't expired, this projectile logic ends early, but the coroutine still continues
|
||||
- [FlipSpriteAngleAt](../../EntityControl/EntityControl%20Methods.md#flipspriteangleat) is called on the entity towards the player with offset (0.0, 90.0, 0.0)
|
||||
- A projectile gets added with this NPCControl as the parent:
|
||||
- sprite index 10 (honey projectile)
|
||||
- starting position at this NPCControl position - its right vector + 1.25 in y
|
||||
- target position being the player position undershot by 1.5 towards the direction of the player
|
||||
- No spin
|
||||
- y angles of the entity.`sprite` angle, no x or z
|
||||
- size of uniform 0.75
|
||||
- `HoneyExplode` particles on destruction
|
||||
- y midpoint of the bezier curve of 2.0
|
||||
- time of 60.0 frames
|
||||
- shadow size multiplier of 0.25
|
||||
- sprite index 10 (honey projectile)
|
||||
- starting position at this NPCControl position - its right vector + 1.25 in y
|
||||
- target position being the player position undershot by 1.5 towards the direction of the player
|
||||
- No spin
|
||||
- y angles of the entity.`sprite` angle, no x or z
|
||||
- size of uniform 0.75
|
||||
- `HoneyExplode` particles on destruction
|
||||
- y midpoint of the bezier curve of 2.0
|
||||
- time of 60.0 frames
|
||||
- shadow size multiplier of 0.25
|
||||
- 0.3 seconds are yielded
|
||||
|
||||
No matter if there was less than 2 projectiles or not, all frames are yielded as long as we are in a `pause`, `minipause`, `inevent` or we are in a `battle` that is `inevent` followed by an additional yield which ends this projectile.
|
||||
|
||||
#### `Turret`
|
||||
The same than `BeeBot` with a few changes:
|
||||
|
||||
- The first yield is 0.7 seconds instead of 0.5
|
||||
- Right before the second FlipSpriteAngleAt, entity.`animstate` is set to 102 (shooting)
|
||||
- The last yield is 0.4 seconds instead of 0.3
|
||||
|
||||
#### `WaspScout`
|
||||
If there's no `projectiles`:
|
||||
|
||||
- entity.`animstate` is set to 100 (preparing to throw)
|
||||
- [FaceTowards](../../EntityControl/EntityControl%20Methods.md#facetowards) is called on the entity to face the player
|
||||
- 0.25 seconds are yielded
|
||||
@@ -206,22 +216,23 @@ If there's no `projectiles`:
|
||||
- The `Toss` sound is played on the entity
|
||||
- [FlipSpriteAngleAt](../../EntityControl/EntityControl%20Methods.md#flipspriteangleat) is called on the entity towards the player with offset (0.0, 90.0, 0.0)
|
||||
- A projectile gets added with this NPCControl as the parent:
|
||||
- sprite index 2 (a brown kunai)
|
||||
- starting position at this NPCControl position - its right vector + 1.75 in y
|
||||
- target position being the player position undershot by 1.5 towards the direction of the player
|
||||
- No spin
|
||||
- y angles of the entity.`sprite` angle and -60.0 in z, no x
|
||||
- size of uniform 0.75
|
||||
- No particles on destruction
|
||||
- y midpoint of the bezier curve of 0.0
|
||||
- time of 45.0 frames
|
||||
- shadow size multiplier of 0.25
|
||||
- sprite index 2 (a brown kunai)
|
||||
- starting position at this NPCControl position - its right vector + 1.75 in y
|
||||
- target position being the player position undershot by 1.5 towards the direction of the player
|
||||
- No spin
|
||||
- y angles of the entity.`sprite` angle and -60.0 in z, no x
|
||||
- size of uniform 0.75
|
||||
- No particles on destruction
|
||||
- y midpoint of the bezier curve of 0.0
|
||||
- time of 45.0 frames
|
||||
- shadow size multiplier of 0.25
|
||||
- 0.75 seconds are yielded
|
||||
|
||||
No matter if there was projectiles or not, all frames are yielded as long as we are in a `pause`, `minipause`, `inevent` or we are in a `battle` that is `inevent` followed by an additional yield which ends this projectile.
|
||||
|
||||
#### `LeafbugArcher`
|
||||
The same than `WaspScout`, but with a few changes:
|
||||
|
||||
- Before facing towards the entity, the `Rope1` sound is played on the entity
|
||||
- The first yield is 0.5 seconds instead of 0.25
|
||||
- The projectile sprite index is 12 (a purple blunt projectile) instead of 2 (a brown kunai)
|
||||
@@ -230,6 +241,7 @@ The same than `WaspScout`, but with a few changes:
|
||||
|
||||
#### `Bandit`
|
||||
If there's no `projectiles`:
|
||||
|
||||
- entity.`animstate` is set to 100 (preparing to throw)
|
||||
- [FaceTowards](../../EntityControl/EntityControl%20Methods.md#facetowards) is called on the entity to face the player
|
||||
- 0.5 seconds are yielded
|
||||
@@ -238,22 +250,23 @@ If there's no `projectiles`:
|
||||
- The `Spin3` sound is played on the entity
|
||||
- [FlipSpriteAngleAt](../../EntityControl/EntityControl%20Methods.md#flipspriteangleat) is called on the entity towards the player with offset (0.0, 90.0, 0.0)
|
||||
- A projectile gets added with this NPCControl as the parent:
|
||||
- sprite index 3 (a shuriken shaped object)
|
||||
- starting position at this NPCControl position - its right vector + 1.0 in y
|
||||
- target position being the player position undershot by 2.0 towards the direction of the player + 1.25 in y
|
||||
- z spin of 20.0
|
||||
- y angles of the entity.`sprite` angle and 90.0 in z, no x
|
||||
- size of uniform 0.75
|
||||
- No particles on destruction
|
||||
- y midpoint of the bezier curve of 1.25
|
||||
- time of 60.0 frames
|
||||
- shadow size multiplier of 0.25
|
||||
- sprite index 3 (a shuriken shaped object)
|
||||
- starting position at this NPCControl position - its right vector + 1.0 in y
|
||||
- target position being the player position undershot by 2.0 towards the direction of the player + 1.25 in y
|
||||
- z spin of 20.0
|
||||
- y angles of the entity.`sprite` angle and 90.0 in z, no x
|
||||
- size of uniform 0.75
|
||||
- No particles on destruction
|
||||
- y midpoint of the bezier curve of 1.25
|
||||
- time of 60.0 frames
|
||||
- shadow size multiplier of 0.25
|
||||
- 0.75 seconds are yielded
|
||||
|
||||
No matter if there was projectiles or not, all frames are yielded as long as we are in a `pause`, `minipause`, `inevent` or we are in a `battle` that is `inevent` followed by an additional yield which ends this projectile.
|
||||
|
||||
#### `ChomperBrute`
|
||||
The same than `Bandit`, but with a few changes:
|
||||
|
||||
- Before the entity.`animstate` is set to 100 (which is opening their mouth), the `Clomp` sound is played on the entity
|
||||
- After the first yields when in many kinds of pause, entity.`animstate` is set to 102 (biting) followed by a yield of 0.2 seconds
|
||||
- Before the FlipSpriteAngleAt, the sound played on the entity is `PingShot` instead of `Toss`
|
||||
|
||||
@@ -19,13 +19,13 @@ The same than [SetPath](SetPath.md), but with the addition that if it's 5555, th
|
||||
The same than [SetPath](SetPath.md), but with the addition that if the frequency is 5555, the entity.[animstate](../../EntityControl/Animations/animstate.md) is set to `Sleep` at the start of the DoBehavior cycle (right after the `returntoheight` logic).
|
||||
|
||||
## Update (Inactive, every 3 frames)
|
||||
Normally, when an entity is in a [forcemove](../EntityControl/EntityControl%20Methods.md#forcemove), [StopForceMove](../EntityControl/EntityControl%20Methods.md#StopForceMove) is called on it, but this behavior is an exception to this where it will not be called here.
|
||||
Normally, when an entity is in a `forcemove`, [StopForceMove](../../EntityControl/EntityControl%20Methods.md#stopforcemove) is called on it, but this behavior is an exception to this where it will not be called here.
|
||||
|
||||
## Update (Common, end)
|
||||
As long as the behavior exist on the NPCControl, `actioncooldown` is set to 1.0 if the player is present and not `digging` while the [message](../../SetText/Notable%20states.md#message) lock is active. This has the overall effect to have the underlying [SetPath](SetPath.md) logic operate as if it has a frequency of 1.0 meaning 1.0 frames of cooldown between movement.
|
||||
As long as the behavior exist on the NPCControl, `actioncooldown` is set to 1.0 if the player is present and not `digging` while the [message](../../../SetText/Notable%20states.md#message) lock is active. This has the overall effect to have the underlying [SetPath](SetPath.md) logic operate as if it has a frequency of 1.0 meaning 1.0 frames of cooldown between movement.
|
||||
|
||||
## LateUpdate (RefreshPlayer)
|
||||
After the new `inrange` value is set and the new value is true a [StealthSpot](ActionBehaviors/StealthAI.md#stealthspot) coroutine is called. There is an exception where this doesn't happen if this is an [Enemy](../NPCType.md#enemy) when the `freezecooldown` or `dizzytime` hasn't expired yet.
|
||||
After the new `inrange` value is set and the new value is true a StealthSpot coroutine is called. There is an exception where this doesn't happen if this is an [Enemy](../NPCType.md#enemy) when the `freezecooldown` or `dizzytime` hasn't expired yet.
|
||||
|
||||
## OnTriggerEnter (If this is an [NPC](../NPCType.md#npc))
|
||||
A StealthSpot coroutine starts if the other collider is the player.`beemerang` and the square distance between this NPCControl and the player is less than 30.0
|
||||
@@ -39,6 +39,7 @@ This is a public coroutine specific to this behavior (the only reason it's publi
|
||||
A Linecast will be performed from this NPCControl position + Vector3.up to the player position + Vector3.up for only layers `Ground`, `NoDigGround` and `Player`.
|
||||
|
||||
For the spotting to register, all of the following conditions must be true:
|
||||
|
||||
- `startlife` is above 20.0
|
||||
- The Linecast hit any `playerdata` entity
|
||||
- The player is free (ignoring flying)
|
||||
@@ -53,12 +54,14 @@ No matter if the spotting was processed or not, a frame is yielded.
|
||||
This is a component specifically involved with this behavior as it is attached to the entity.`detect` on SetUp. Its job is to be the way the NPCControl can spot the player with 2 trigger colliders.
|
||||
|
||||
These colliders are added on the component's Start:
|
||||
|
||||
- A trigger SphereCollider with radius 1.5 and default position (meaning at the entity.`detect`'s position)
|
||||
- A trigger BoxCollider with size (2.5, 2.0, NPCControl's `battleids[1]`) and center (0.0, 1.5, half of NPCControl's `battleids[1]` floored)
|
||||
|
||||
The Start also puts the entity.`detect` GameObject in layer 2, the built in layer of Unity to ignore raycasts.
|
||||
|
||||
From there, the only interesting logic this component has is an OnTriggerEnter where the method will call StealthSpot under the following conditions:
|
||||
|
||||
- The player must be present and free (flying counts as not free)
|
||||
- If the other collider is the player.`beemerang`, it must be less than 30.0 away from the entity.`detect`
|
||||
- If it's the player, the internal cooldown of the component must be expired
|
||||
|
||||
@@ -13,6 +13,7 @@ It can be used as the default behavior while [ChaseWhenAnim](ChaseWhenAnim.md) i
|
||||
If the entity.`animstate` is `Walk` (or `Idle` if the `behaviorcooldown` expired), this acts as an alias to [Wander](Wander.md).
|
||||
|
||||
Otherwise, if the current entity.`animstate` isn't the frequency:
|
||||
|
||||
- The `behaviorcooldown` is set to 20.0 (prevents another [Wander](Wander.md) cycle to process for 20.0 frames when entity.`animstate` is `Idle`)
|
||||
- [StopForceMove](../../EntityControl/EntityControl%20Methods.md#StopForceMove) is called on the entity
|
||||
- The entity.`animstate` is set to frequency
|
||||
|
||||
@@ -18,6 +18,7 @@ The entity.`rigid` is unlocked with [LockRigid(false)](../../EntityControl/Entit
|
||||
If `returntoheight` is true, entity.`height` is set to a lerp from the existing one to entity.`initialheight` with a factor of 0.1
|
||||
|
||||
From there, there is an early exit path if the entity is in a `forcemove` and any of the following is true:
|
||||
|
||||
- entity.`hitwall` is true
|
||||
- entity.`onground` is false
|
||||
- entity.`detect` is present and [HasGroundAhead](../../EntityControl/EntityControl%20Methods.md#hasgroundahead) from the entity.`forcetarget` returns false
|
||||
@@ -25,12 +26,14 @@ From there, there is an early exit path if the entity is in a `forcemove` and an
|
||||
When the above is fufilled, [StopForceMove](../../EntityControl/EntityControl%20Methods.md#stopforcemove) is called with the `basestate` and this DoBehavior cycle is ended early. This is because the game concluded it is no longer possible to move further towards this position.
|
||||
|
||||
If we are cleared to continue, there are 4 possible branches this DoBehavior can takes (only the first one that applies is taken checked in this order):
|
||||
|
||||
- `actioncooldown` expired (the main wandering logic)
|
||||
- `maxtries` is exactly 10
|
||||
- The distance between entity.`startpos` and this position is higher than the `teleportradius` or `maxtries` is 20 or above (meaning it went too far away or there's too much failed wander attempts)
|
||||
- The entity is in a `forcemove`
|
||||
|
||||
If none of the branches above are taken, it means to wait before the next wander:
|
||||
|
||||
- `walkcooldown` is set to 0.0
|
||||
- `trycount` is set to 0
|
||||
- `actioncooldown` is decremented by the game's frametime
|
||||
@@ -42,6 +45,7 @@ This branch is essentially the main logic that manages the movement to the next
|
||||
The attempted next vector is 1/3 of a random one between (-`wanderradius`, 0.5, -`wanderradius`) and (`wanderradius`, 0.5, `wanderradius`) which is then added to the entity.`startpos` as the `wanderradius` is relative to it. When generated, the entity.`moverotater` is set to look at it regardless if it's accepted or not.
|
||||
|
||||
If the vector is less than `radiuslimit` away from the current position (meaning it's not too far to move to), then it is accepted which makes the following happen:
|
||||
|
||||
- [MoveTowards](../../EntityControl/EntityControl%20Methods.md#movetowards) is called on the entity to move to the vector at default everything with the exception that the y component is ignored
|
||||
- The entity.`detect` is set to LookAt the vector
|
||||
- `actioncooldown` is set to be random between 1/3 of the frequency and the frequency itself
|
||||
@@ -56,6 +60,7 @@ The purpose of this field and `maxtries` is to regulate the timeout logic. If it
|
||||
|
||||
### Too far or too much failed wander attempts
|
||||
This is basically a warp to force the entity to teleport to its `startpos`:
|
||||
|
||||
- DeathSmoke particles are played at this position if the entity is `incamera`
|
||||
- The position is set to the entity.`startpos`
|
||||
- The entity.`rigid` velocity is zeroed out
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Enemy
|
||||
An enemy is a non interactable entity that supports [ActionBehaviors](ActionBehaviors.md) with the ability to initiate a battle encounter with the player consisting of up to 4 [enemy](../../Enums%20and%20IDs/Enemies.md). It also features special logic to handle all of this including cases where it's frozen or dizzy. It is the NPCType with the most exclusive logic available.
|
||||
An enemy is a non interactable entity that supports [ActionBehaviors](ActionBehaviors.md) with the ability to initiate a battle encounter with the player consisting of up to 4 [enemies](../../Enums%20and%20IDs/Enemies.md). It also features special logic to handle all of this including cases where it's frozen or dizzy. It is the NPCType with the most exclusive logic available.
|
||||
|
||||
## Data arrays
|
||||
- `vectordata`: The list of random standard [item](../../Enums%20and%20IDs/Items.md) the enemy can potentially drop in the x components of each element when EntityControl.[Death](../EntityControl/Notable%20methods/Death.md) is called on the entity. For the drop to happen on a given element, its y component (if it's not negative) must correspond to a [flag](../../Flags%20arrays/flags.md) slot whose value is true. If any element's y component is -2 however, the first occurence where this is the case will override the drop as it means this will dropped as a key item and it will also bypass the random check performed by EntityControl.Death
|
||||
@@ -19,6 +19,7 @@ The `lockcooldown` of the `arrow` is set to true only if `freezecooldown` is abo
|
||||
|
||||
## Update (Active, main logic, overrides)
|
||||
Only 1 of 3 cases happens here (checked in order):
|
||||
|
||||
- This is a frozen enemy (the `freezecooldown` hasn't expired yet)
|
||||
- This is a frozen entity of any kind (it has an `icecube`, but in practice, this can only happen if an enemy is frozen because it's only on them that [Freeze](../EntityControl/Notable%20methods/Freeze%20handling.md#Freeze) is called)
|
||||
- This is a dizzy enemy (the `dizzytime` is above 0.0)
|
||||
@@ -31,6 +32,7 @@ If the entity.`rigid` y velocity is not between -0.1 and 0.1 inclusive, its x an
|
||||
The absolute position is clamped to be within a radius of `radiuslimit` where the center is at the entity.`startpos` ignoring the y component.
|
||||
|
||||
The following occurs:
|
||||
|
||||
- The `pusher` is disabled if it was present
|
||||
- The `dizzytime` is set to -1000.0
|
||||
- The entity.`spin` is zeroed out
|
||||
@@ -59,6 +61,7 @@ If the player is present and it is `standingon` this `boxcol`, then the player.e
|
||||
The layer is set to `templayer` if it wasn't -1 before it is set to -1. This restores the value it had when the entity was frozen previously.
|
||||
|
||||
The following occurs:
|
||||
|
||||
- entity.`shadow` is enabled if `hasshadow` was true
|
||||
- entity.`ccol` is enabled
|
||||
- entity.`boxcol` is disabled if it was present
|
||||
@@ -70,12 +73,14 @@ The following occurs:
|
||||
### Dizzy enemy
|
||||
The `disguiseobj` is disabled if present.
|
||||
|
||||
[StartBattle](StartBattle.md) is called if all of the following are true:
|
||||
[StartBattle](Notable%20methods/StartBattle.md) is called if all of the following are true:
|
||||
|
||||
- It's been more than 20 frames since the `startlife`
|
||||
- We aren't in a `pause`, `minipause` or [message](../../SetText/Notable%20states.md#message)
|
||||
- The player is present and the distance between it and this enemey is \<= the entity.`ccol` radius + 1.1
|
||||
- The player is present and the distance between it and this enemey is <= the entity.`ccol` radius + 1.1
|
||||
|
||||
The following occurs:
|
||||
|
||||
- entity.`height` is decreased by - 0.075 clamped from 0.0 to 999.0
|
||||
- entity.`spin` is set to (0, `dizzytime` / 5 clamped from 0.0 to 15.0, 0.0)
|
||||
- entity.`overrideanim` is set to true
|
||||
@@ -89,11 +94,13 @@ The following occurs:
|
||||
These logic can happen as part of a standard active Update if none of the above cases applied and we aren't `trapped`.
|
||||
|
||||
If the `dizzytime` is above -999.0, it is set to -1000.0 with the following adjustements being done on the entity which essentially ends the dizzyness:
|
||||
|
||||
- enity.`spin` gets zeroed out
|
||||
- enity.[animstate](../EntityControl/Animations/animstate.md) gets set back to entity.`basestate`
|
||||
- enity.`overrideanim` is set to false
|
||||
|
||||
[StartBattle](StartBattle.md) is called if all of the following are true:
|
||||
[StartBattle](Notable%20methods/StartBattle.md) is called if all of the following are true:
|
||||
|
||||
- It's been more than 20 frames since the `startlife`
|
||||
- We aren't in a `pause`, `minipause` or [message](../../SetText/Notable%20states.md#message)
|
||||
- The player is present and the distance between it and this enemey is \<= the entity.`ccol` radius + 1.1
|
||||
@@ -103,19 +110,21 @@ For every 3 frames, if the entity is in a [forcemove](../EntityControl/EntityCon
|
||||
|
||||
## LateUpdate (Non `dummy` and entity is `incamera`)
|
||||
If the `eventid` is 0 and the entity `iskill` while we aren't in `pause`, `minipause` and `inevent`, some logic occurs depending on the `respawntimer`:
|
||||
|
||||
- If it is -100.0 or less, it is set to `eventid`,
|
||||
- If it is above 0.0, it is decreased by the game's frametime
|
||||
- If it's negative, but above -100.0, [RespawnEnemy](RespawnEnemy.md) is called using the entity `spawnpoint`, the entity `iskill` is set to false and `respawntimer` is set to -110.0
|
||||
- If it's negative, but above -100.0, [RespawnEnemy](Notable%20methods/RespawnEnemy.md) is called using the entity `spawnpoint`, the entity `iskill` is set to false and `respawntimer` is set to -110.0
|
||||
|
||||
## LateUpdate (Every 3 frames during RefreshPlayer)
|
||||
When the `inrange` value changes:
|
||||
|
||||
- If the new `inrange` is true, the change is only accepted if both the `freezecooldown` and the `dizzytime` expired. If they have, the `Find` sound is played if the player wasn't `digging`
|
||||
- If the new `inrange` is false and both `freezecooldown` and `dizzytime` expired while `behaviorroutine` isn't in progress:
|
||||
- entity.`emoticonid` is set to 1 (?)
|
||||
- entity.`emoticoncooldown` is set to 70.0
|
||||
- [StopForceMove](../EntityControl/EntityControl%20Methods.md#stopforcemove) is called with the `Idle` target state
|
||||
- The `Lost` sound is played
|
||||
- entity.`overrideonlyflip` is set to false
|
||||
- entity.`emoticonid` is set to 1 (?)
|
||||
- entity.`emoticoncooldown` is set to 70.0
|
||||
- [StopForceMove](../EntityControl/EntityControl%20Methods.md#stopforcemove) is called with the `Idle` target state
|
||||
- The `Lost` sound is played
|
||||
- entity.`overrideonlyflip` is set to false
|
||||
|
||||
## OnTriggerEnter
|
||||
What happens here depends on the other collider, only one branches is ran and if it doesn't apply, nothing happens.
|
||||
@@ -125,12 +134,12 @@ This does nothing if the entity is `digging` or its [animid](../../Enums%20and%2
|
||||
|
||||
- The other gameObject is destroyed if it had a RigidBody
|
||||
- The `freezecooldown` is set to 300.0 with some exceptions:
|
||||
- It is set to 30.0 if the current [map](../../Enums%20and%20IDs/Maps.md) is `GiantLairDeadLands1` or `GiantLairDeadLands2`
|
||||
- It is set to `freezetime` clamped from 600.0 to infinity if the Extra Freeze [medal](../../Enums%20and%20IDs/Medal.md) is equipped or `extrafreeze` is true
|
||||
- It is set to 30.0 if the current [map](../../Enums%20and%20IDs/Maps.md) is `GiantLairDeadLands1` or `GiantLairDeadLands2`
|
||||
- It is set to `freezetime` clamped from 600.0 to infinity if the Extra Freeze [medal](../../Enums%20and%20IDs/Medal.md) is equipped or `extrafreeze` is true
|
||||
- If it's a `ToeBiter` and `internaltransform[0]` (his boulder) is present, it is destroyed
|
||||
- entity.`rigid` x and z velocity are zeroed out
|
||||
- entity.`onground` is set to true
|
||||
- [StopForceBehavior](StopForceBehavior.md) is called
|
||||
- [StopForceBehavior](Notable%20methods/StopForceBehavior.md) is called
|
||||
|
||||
### The other tag is `BeetleDash` or `BeetleHorn`
|
||||
The `BeetleHorn` tag only counts here if the player isn't `dashing`. This does nothing if `collisionammount` is 0, the entity is `dead` or `digging` or the `touchcooldown` hasn't expired yet.
|
||||
@@ -138,15 +147,15 @@ The `BeetleHorn` tag only counts here if the player isn't `dashing`. This does n
|
||||
- TempIgnoreColision is called on the entity with the other collider which ignores all collision between the entity.`ccol` / entity.`detect` and the other collider for 0.5 seconds
|
||||
- The `Damage0` sound is played
|
||||
- If the other collider tag was `BeetleDash`, the `freezecooldown` is set to 0.0
|
||||
- A [Dizzy](Dizzy.md) coroutine is started for 120.0 frames with force launch with the direction being the normalized direction from this enemy to the player * 5.0
|
||||
- A [Dizzy](Notable%20methods/Dizzy.md) coroutine is started for 120.0 frames with force launch with the direction being the normalized direction from this enemy to the player * 5.0
|
||||
- `collisionammount` is incremented
|
||||
|
||||
### The other tag is `BeeRang`
|
||||
This does nothing if `collisionammount` is 0, the entity is `dead` or `digging` or the `touchcooldown` hasn't expired yet.
|
||||
|
||||
- The `WoodHit` sound is played on the entity
|
||||
- A [Dizzy](Dizzy.md) coroutine is started for 80.0 frames with no pushforce or force launch
|
||||
- A [Dizzy](Notable%20methods/Dizzy.md) coroutine is started for 80.0 frames with no pushforce or force launch
|
||||
- `collisionammount` is incremented
|
||||
|
||||
### The other collider is owned by the player
|
||||
If we aren't in a `minipause`, `pause` or `inevent`, [StartBattle](StartBattle.md) is called TODO: this seems contradictory with the Update logic ???.
|
||||
If we aren't in a `minipause`, `pause` or `inevent`, [StartBattle](Notable%20methods/StartBattle.md) is called TODO: this seems contradictory with the Update logic ???.
|
||||
|
||||
@@ -7,18 +7,19 @@ Most of the calls to that method comes from PlayerControl's GetInput when it det
|
||||
|
||||
## Enum table
|
||||
The following is a table of the different `Interaction` values (NOT REFERENCED means the game never reference the value meaning it has not logic backing it, UNUSED means the behavior has logic, but it is either dead or not practically used under normal gameplay):
|
||||
|
||||
|Value|Name|Description|
|
||||
|----:|----|-----------|
|
||||
|0|None|NOT REFERENCED, No operations|
|
||||
|1|[Talk](Interaction/Talk.md)|Calls [SetText](../../../SetText/SetText.md) in [Dialogue mode](../../../SetText/Dialogue%20mode.md#dialogue-mode) using the text from the return of [GetDialogue](../Notable%20methods/GetDialogue.md). It also gives the NPC a chatting emoticon when the NPC is in the `npc` interact list of the player.|
|
||||
|2|[Check](Interaction/Check.md)|An alias of [Talk](Talk.md), but the emoticon the NPC gets is the blue ? one when it is in the `npc` list of the player.|
|
||||
|3|[SavePoint](Interaction/SavePoint.md)|The same than [Talk](Talk.md), but the [SetText](../../../SetText/SetText.md) input string is hardcoded. The string contains a [prompt](../../../SetText/Individual%20commands/Prompt.md) command where the confirm option leads to a line with a [save](../../../SetText/Individual%20commands/Save.md) command which will actually saves the game.|
|
||||
|4|[Event](Interaction/Event.md)|Start the [event](../../../Enums%20and%20IDs/Events.md) whose id is `eventid` with this NPC as the caller.|
|
||||
|5|[TalkReturnToOriginalFlip](Interaction/TalkReturnToOriginalFlip.md)|UNUSED, An alias of [Talk](Talk.md), but only the Interact logic remains.|
|
||||
|6|[Shop](Interaction/Shop.md)|At loading time, this interaction is only for indicative purposes to build a [shop system](../Shop%20system.md). At runtime after the shop system has been built, this is the interaction of a shelved item which is a `SemiNPC` [item entity](../../EntityControl/Item%20entity.md) and the interaction calls [SetText](../../../SetText/SetText.md) with the shop keeper's buying dialogue.|
|
||||
|7|[ShopKeeper](Interaction/ShopKeeper.md)|Similar to [talk](Talk.md), but with a shop keeper buying or selling dialogue line.|
|
||||
|1|[Talk](Interaction/Talk.md)|Calls [SetText](../../SetText/SetText.md) in [Dialogue mode](../../SetText/Dialogue%20mode.md#dialogue-mode) using the text from the return of [GetDialogue](Notable%20methods/GetDialogue.md). It also gives the NPC a chatting emoticon when the NPC is in the `npc` interact list of the player.|
|
||||
|2|[Check](Interaction/Check.md)|An alias of `Talk`, but the emoticon the NPC gets is the blue ? one when it is in the `npc` list of the player.|
|
||||
|3|[SavePoint](Interaction/SavePoint.md)|The same than `Talk`, but the [SetText](../../SetText/SetText.md) input string is hardcoded. The string contains a [prompt](../../SetText/Individual%20commands/Prompt.md) command where the confirm option leads to a line with a [save](../../SetText/Individual%20commands/Save.md) command which will actually saves the game.|
|
||||
|4|[Event](Interaction/Event.md)|Start the [event](../../Enums%20and%20IDs/Events.md) whose id is `eventid` with this NPC as the caller.|
|
||||
|5|[TalkReturnToOriginalFlip](Interaction/TalkReturnToOriginalFlip.md)|UNUSED, An alias of `Talk`, but only the Interact logic remains.|
|
||||
|6|[Shop](Interaction/Shop.md)|At loading time, this interaction is only for indicative purposes to build a [shop system](Shop%20system.md). At runtime after the shop system has been built, this is the interaction of a shelved item which is a `SemiNPC` [item entity](../EntityControl/Item%20entity.md) and the interaction calls [SetText](../../SetText/SetText.md) with the shop keeper's buying dialogue.|
|
||||
|7|[ShopKeeper](Interaction/ShopKeeper.md)|Similar to `Talk`, but with a shop keeper buying or selling dialogue line.|
|
||||
|8|[QuestBoard](Interaction/QuestBoard.md)|The interaction for a quest board which allows to consult the 3 quest boards and take any open quests by having a dialogue with the caretaker of the quest board which is another NPCControl.|
|
||||
|9|[StorageAnt](Interaction/StorageAnt.md)|The same than [Talk](Talk.md), but the [SetText](../../../SetText/SetText.md) input string is hardcoded. It is the Ant Storage Service text unless [flag](../../../Flags%20arrays/flags.md) 180 (received the Ant Storage Service tutorial) is false where it's the tutorial. This also sets [flag](../../../Flags%20arrays/flags.md) 180 and 349 (using the Ant Storage Service, allows multiselect) to true.|
|
||||
|10|[CaravanBadge](Interaction/CaravanBadge.md)|Similar than [Shop](Shop.md), but for interacting with a shelved Caravan prize medal which only involve some parts of the [shop system](../Shop%20system.md) because it is handled entirely on its own with its own set of data.|
|
||||
|11|[VenusHeal](Interaction/VenusHeal.md)|The same than [Talk](Talk.md), but the [SetText](../../../SetText/SetText.md) input string is hardcoded to `commondialogue[60]` (the Venus bud healing text).|
|
||||
|12|[LockedDoor](Interaction/LockedDoor.md)|Start [event](../../../Enums%20and%20IDs/Events.md) 59 (Interacting with an object that requires a key item).|
|
||||
|9|[StorageAnt](Interaction/StorageAnt.md)|The same than `Talk`, but the [SetText](../../SetText/SetText.md) input string is hardcoded. It is the Ant Storage Service text unless [flag](../../Flags%20arrays/flags.md) 180 (received the Ant Storage Service tutorial) is false where it's the tutorial. This also sets [flag](../../Flags%20arrays/flags.md) 180 and 349 (using the Ant Storage Service, allows multiselect) to true.|
|
||||
|10|[CaravanBadge](Interaction/CaravanBadge.md)|Similar than `Shop`, but for interacting with a shelved Caravan prize medal which only involve some parts of the [shop system](Shop%20system.md) because it is handled entirely on its own with its own set of data.|
|
||||
|11|[VenusHeal](Interaction/VenusHeal.md)|The same than `Talk`, but the [SetText](../../SetText/SetText.md) input string is hardcoded to `commondialogue[60]` (the Venus bud healing text).|
|
||||
|12|[LockedDoor](Interaction/LockedDoor.md)|Start [event](../../Enums%20and%20IDs/Events.md) 59 (Interacting with an object that requires a key item).|
|
||||
@@ -15,19 +15,20 @@ The same than [Shop](Shop.md), but CaravanMedalSet features extended logic.
|
||||
|
||||
### CaravanMedalSet
|
||||
The logic for this interaction changes as it doesn't follow the usual [Shop system](../Shop%20system.md) workflow:
|
||||
|
||||
- `shopkeeper` is set to the entity resolved using `data[0]` as the [entity id](../../../SetText/Common%20commands%20id%20schemes/Entity%20id.md)
|
||||
- The array of the currently available prize medals at the caravan is obtained via PrizeBadges(true)
|
||||
- If the array is empty, this object gets destroyed as there's no need to have it
|
||||
- Otherwise:
|
||||
- The prize [medals](../../../Enums%20and%20IDs/Medal.md) array is shuffled
|
||||
- MainManager.`caravanorder` is set to the shuffled array
|
||||
- entity.`item` is set to true making it an [item entity](../../EntityControl/Item%20entity.md)
|
||||
- entity.`animid` is set to 2 (medal)
|
||||
- entity.`animstate` is set to the first element of the shuffled array (this is the first prize medal id of the array)
|
||||
- entity.`itemstate` is set to entity.`animstate`
|
||||
- [entitytype](../NPCType.md) is set to [SemiNPC](../Shop%20system.md#seminpc) which behaves the same than the ones used in the shop system
|
||||
- If we are rerolling (which only happens if we are calling from a [kill](../../../SetText/Individual%20commands/Kill.md) or [rerollshops](../../../SetText/Individual%20commands/Rerollshops.md) commands), DeathSmoke particles are played at this NPCControl position
|
||||
- The first element of MainManager.`caravanorder` is removed
|
||||
- The prize [medals](../../../Enums%20and%20IDs/Medal.md) array is shuffled
|
||||
- MainManager.`caravanorder` is set to the shuffled array
|
||||
- entity.`item` is set to true making it an [item entity](../../EntityControl/Item%20entity.md)
|
||||
- entity.`animid` is set to 2 (medal)
|
||||
- entity.`animstate` is set to the first element of the shuffled array (this is the first prize medal id of the array)
|
||||
- entity.`itemstate` is set to entity.`animstate`
|
||||
- [entitytype](../NPCType.md) is set to [SemiNPC](../Shop%20system.md#seminpc) which behaves the same than the ones used in the shop system
|
||||
- If we are rerolling (which only happens if we are calling from a [kill](../../../SetText/Individual%20commands/Kill.md) or [rerollshops](../../../SetText/Individual%20commands/Rerollshops.md) commands), DeathSmoke particles are played at this NPCControl position
|
||||
- The first element of MainManager.`caravanorder` is removed
|
||||
- entity.`rigid` gets its gravity disabled with all constraints frozen
|
||||
- The position is set to entity.`startpos`
|
||||
- entity.`ccol` is disabled
|
||||
@@ -43,14 +44,14 @@ The same than [Shop](Shop.md).
|
||||
- [flagvar](../../../Flags%20arrays/flagvar.md) 1 is set to the buying price of the [medal](../../../Enums%20and%20IDs/Medal.md) whose id is the entity `animstate` unless [flag](../../../Flags%20arrays/flags.md) 681 (MYSTERY? is active) which forces it to 35
|
||||
- [flagstring](../../../Flags%20arrays/flagstring.md) 0 to be the name of the [medal](../../../Enums%20and%20IDs/Medal.md) whose id is the entity `animstate` unless [flag](../../../Flags%20arrays/flags.md) 681 (MYSTERY? is active) which forces it to `menutext[59]` (?????)
|
||||
- Call [SetText](../../../SetText/SetText.md) in [dialogue mode](../../../SetText/Dialogue%20mode.md) using `data[1]` as the [dialogue line id](../../../SetText/Common%20commands%20id%20schemes/Dialogue%20line%20id.md) for the input string (the shop keeper's caravan medal dialogue line) with the following:
|
||||
- [fonttype](../../../SetText/Notable%20states.md#fonttype) of `BubblegumSans`
|
||||
- `messagebreak` as the linebreak
|
||||
- No tridimensional
|
||||
- No position offset
|
||||
- No camera offset
|
||||
- size of Vector3.one
|
||||
- The parent is the entity resolved using `data[0]` (the shop keeper map entity id) as the [entity id](../../../SetText/Common%20commands%20id%20schemes/Entity%20id.md)
|
||||
- This NPCControl as the caller
|
||||
- [fonttype](../../../SetText/Notable%20states.md#fonttype) of `BubblegumSans`
|
||||
- `messagebreak` as the linebreak
|
||||
- No tridimensional
|
||||
- No position offset
|
||||
- No camera offset
|
||||
- size of Vector3.one
|
||||
- The parent is the entity resolved using `data[0]` (the shop keeper map entity id) as the [entity id](../../../SetText/Common%20commands%20id%20schemes/Entity%20id.md)
|
||||
- This NPCControl as the caller
|
||||
- All `playerdata` entities have [FaceTowards](../../EntityControl/EntityControl%20Methods.md) call on them to face the entity resolved using `data[0]`(the shop keeper map entity id) as the [entity id](../../../SetText/Common%20commands%20id%20schemes/Entity%20id.md)
|
||||
|
||||
## SetBadgeShop
|
||||
|
||||
@@ -12,6 +12,7 @@ Start the [event](../../../Enums%20and%20IDs/Events.md) whose id is `eventid` wi
|
||||
|
||||
## PlayerControl.LateUpdate
|
||||
entity.`emoticonid` gets set to 1 (a blue ?) and entity.`emoticoncooldown` gets set to 2.0 if all of the following conditions are met:
|
||||
|
||||
- We aren't in a `pause` or `minipause`
|
||||
- The [message](../../../SetText/Notable%20states.md#message) lock is released
|
||||
- The player isn't `digging`, `flying`, `startdig` or in `shield`
|
||||
|
||||
@@ -9,6 +9,7 @@ Start [event](../../../Enums%20and%20IDs/Events.md) 59 with this as the caller.
|
||||
|
||||
## PlayerControl.LateUpdate
|
||||
entity.`emoticonid` gets set to 1 (a blue ?) and entity.`emoticoncooldown` gets set to 2.0 if all of the following conditions are met:
|
||||
|
||||
- We aren't in a `pause` or `minipause`
|
||||
- The [message](../../../SetText/Notable%20states.md#message) lock is released
|
||||
- The player isn't `digging`, `flying`, `startdig` or in `shield`
|
||||
|
||||
@@ -7,7 +7,7 @@ None.
|
||||
## Data meaning
|
||||
- `data[0]`: An [entity id](../../../SetText/Common%20commands%20id%20schemes/Entity%20id.md) that corresponds to the caretaker of the quest board
|
||||
- `data[1]`: A [dialogue line id](../../../SetText/Common%20commands%20id%20schemes/Dialogue%20line%20id.md) of what the caretaker of the quest board will say when accepting to take a quest. The line must contain a [prompt](../../../SetText/Individual%20commands/Prompt.md) for the system to work because this line will get prepended with a [questprompt](../../../SetText/Individual%20commands/Questprompt.md) when confirming the quest. Check the documentation of that command to learn more about how this all work
|
||||
- `data[2]`: If it's not negative, this is a [flag](../../../Flags%20arrays/flags.md) slot that if it's false, [Interact](../Interact.md) will be called on the `npcdata` of the map entity whose id is `data[0]`.
|
||||
- `data[2]`: If it's not negative, this is a [flag](../../../Flags%20arrays/flags.md) slot that if it's false, [Interact](../Notable%20methods/Interact.md) will be called on the `npcdata` of the map entity whose id is `data[0]`.
|
||||
- `vectordata[0]`: The camera position to move before showing the quest board UI, set to instance.`camoffset`
|
||||
- `vectordata[1]`: The camera angles to move before showing the quest board UI, set to instance.`camangleoffset`
|
||||
- `vectordata[2].x`: The camera speed to usd while moving the camera before showing the quest board UI, set to instance.`camspeed`
|
||||
@@ -17,12 +17,13 @@ None.
|
||||
The `tattleid` is set to -1 ("L.", this isn't supposed to be tattled as this text is an internal error message).
|
||||
|
||||
## Interact
|
||||
If `data[2]` isn't negative and its corresponding [flag](../../../Flags%20arrays/flags.md) slot is false, [Interact](../Interact.md) is called on the `npcdata` of the map entity whose id is `data[0]` without any arguments.
|
||||
If `data[2]` isn't negative and its corresponding [flag](../../../Flags%20arrays/flags.md) slot is false, [Interact](../Notable%20methods/Interact.md) is called on the `npcdata` of the map entity whose id is `data[0]` without any arguments.
|
||||
|
||||
Otherwise, an OpenQuestBoard coroutine is started with the map entity whose id is `data[0]` as the caretaker and this as the caller.
|
||||
|
||||
## PlayerControl.LateUpdate
|
||||
entity.`emoticonid` gets set to 1 (a blue ?) and entity.`emoticoncooldown` gets set to 2.0 if all of the following conditions are met:
|
||||
|
||||
- We aren't in a `pause` or `minipause`
|
||||
- The [message](../../../SetText/Notable%20states.md#message) lock is released
|
||||
- The player isn't `digging`, `flying`, `startdig` or in `shield`
|
||||
@@ -32,6 +33,7 @@ entity.`emoticonid` gets set to 1 (a blue ?) and entity.`emoticoncooldown` gets
|
||||
This is a public static coroutine that is exclusive to this interaction. It receives an EntityControl as the caretaker (the entity whose id is `data[0]`) and an NPCControl as the caller (which is this NPCControl).
|
||||
|
||||
Its job is to setup the opening of the quest board UI and also setups the [ItemList](../../../ItemList/ItemList.md) that shows the quests. Since this coroutine involves a lot of verbose rendering, its documentation is going to paraphrase a lot:
|
||||
|
||||
- All huds elements are hidden (including the berry count and discovery ones) by setting `discoveryhud`, `showmoney` and `hudcooldown` to 0.0
|
||||
- The camera position is saved to the temporary files via SaveCameraPosition(true)
|
||||
- [flag](../../../Flags%20arrays/flags.md) 2 (unchecked new quests) is set to true
|
||||
|
||||
@@ -9,6 +9,7 @@ The [SavePoint](../ObjectTypes/SavePoint.md) object is the only object where an
|
||||
|
||||
## Interact
|
||||
Calls [SetText](../../../SetText/SetText.md) in [dialogue mode](../../../SetText/Dialogue%20mode.md) with the input string being `|`[boxstyle](../../../SetText/Individual%20commands/Boxstyle.md)`,4||`[bleep](../../../SetText/Individual%20commands/Bleep.md)`,2,1,1|` + `menutext[4]` (the save prompt text) + `|`[prompt](../../../SetText/Individual%20commands/Prompt.md)`,menu,0.7,2,7,78,5,6|`:
|
||||
|
||||
- The [fonttype](../../../SetText/Notable%20states.md#fonttype) is `BubblegumSans`
|
||||
- The default `messagebreak` is used as the linebreak
|
||||
- No tridimensional
|
||||
|
||||
@@ -23,14 +23,17 @@ If this is an `item` entity, the entity `animstate` is set to its `itemstate`.
|
||||
The [flagvar](../../../Flags%20arrays/flagvar.md) 0 is set to the entity `animstate`
|
||||
|
||||
If the entity `animid` is 2 (it's a medal):
|
||||
|
||||
- [flagvar](../../../Flags%20arrays/flagvar.md) 1 is set to the buying price of the [medal](../../../Enums%20and%20IDs/Medal.md) whose id is the entity `animstate` unless [flag](../../../Flags%20arrays/flags.md) 681 (MYSTERY? is active) which forces it to 35.
|
||||
- [flagstring](../../../Flags%20arrays/flagstring.md) 0 to be the name of the [medal](../../../Enums%20and%20IDs/Medal.md) whose id is the entity `animstate` unless [flag](../../../Flags%20arrays/flags.md) 681 (MYSTERY? is active) which forces it to `menutext[59]` (?????).
|
||||
|
||||
Otherwise:
|
||||
|
||||
- [flagvar](../../../Flags%20arrays/flagvar.md) 1 is set to the buying price of the [item](../../../Enums%20and%20IDs/Items.md) * `mmulti` then ceiled whose id is the entity `animstate` and type being its `animid`. `mmulti` was set during SetUp using a value from the shop entity data.
|
||||
- [flagstring](../../../Flags%20arrays/flagstring.md) 0 to be the name of the [item](../../../Enums%20and%20IDs/Items.md) whose id is the entity `animstate` and type being its `animid`.
|
||||
|
||||
From there, the rest acts as if we interacted with the same logic than [ShopKeeper](ShopKeeper.md) with the `args` being `buy` which will call [SetText](../../../SetText/SetText.md) in [dialogue mode](../../../SetText/Dialogue%20mode.md) using `shopkeeper.dialogues[6].y` as the [dialogue line id](../../../SetText/Common%20commands%20id%20schemes/Dialogue%20line%20id.md) for the input string (the buying SetText line) with the following:
|
||||
|
||||
- [fonttype](../../../SetText/Notable%20states.md#fonttype) of `BubblegumSans`
|
||||
- `messagebreak` as the linebreak
|
||||
- No tridimensional
|
||||
@@ -44,7 +47,8 @@ Finally, all `playerdata` entities have [FaceTowards](../../EntityControl/Entity
|
||||
|
||||
## LateUpdate (Every 3 frames, non `dummy` and the entity is `incamera`)
|
||||
This logic mainly determines if we should create or destroy the `descwindow`. It is created with [CreateDescWindow(true)](../Notable%20methods/CreateDescWindow.md) if all of the following are true:
|
||||
- [message](../../SetText/Notable%20states.md#message) is released
|
||||
|
||||
- [message](../../../SetText/Notable%20states.md#message) is released
|
||||
- We aren't in a `pause`
|
||||
- We are `inrange`
|
||||
- The first NPCControl (if it exists) in the interact list of the player is this one
|
||||
@@ -53,7 +57,8 @@ This logic mainly determines if we should create or destroy the `descwindow`. It
|
||||
|
||||
On top of this before the creation, if the `shopkeeper`'s `dialogues[1].y` is 1 (it's a medal shop), the `showmoney` is set to 1.0 and 0.0 otherwise (this shows and hides the berry count HUD element accordingly).
|
||||
|
||||
If we didn't created the description window, it is destroyed via DestroyDescWindow if `descwindow` isn't null, [message](../../SetText/Notable%20states.md#message) is released and at least one of the following is true:
|
||||
If we didn't created the description window, it is destroyed via DestroyDescWindow if `descwindow` isn't null, [message](../../../SetText/Notable%20states.md#message) is released and at least one of the following is true:
|
||||
|
||||
- The `insideid` doesn't match the current one
|
||||
- We are in a `pause`
|
||||
- There are no NPCControl in the player interact list or the first one is not this NPCControl
|
||||
@@ -76,6 +81,7 @@ Any NPCControl with this interaction will block the unifixing unless force is tr
|
||||
|
||||
## [SetText](../../../SetText/SetText.md)
|
||||
This interactions affects SetText in several ways:
|
||||
|
||||
- [shopline](../../../SetText/Individual%20commands/Shopline.md) commands are only processed by [OrganizeLines](../../../SetText/Related%20Systems/Automatic%20Line%20Breaks/OrganiseLines.md#organiselines) if the first NPCControl in the player.`npc` list has this interaction
|
||||
- In [dialogue setup](../../../SetText/Life%20Cycle.md#dialogue-setup), if the caller has this interaction while its `shopkeeper.dialogues[1].y` isn't 1 (the shop accepts regular berries as currency), the berry count HUD will be shown at the start of the call
|
||||
- In [dialogue setup](../../../SetText/Life%20Cycle.md#dialogue-setup), if the caller has this interaction while we aren't `inevent`, [FaceTowards](../../EntityControl/EntityControl%20Methods.md#facetowards) will be called on player.entity to face towards the caller.`shopkeeper` instead of the caller itself
|
||||
@@ -85,6 +91,7 @@ This interactions affects SetText in several ways:
|
||||
|
||||
## PlayerControl.LateUpdate
|
||||
entity.`emoticonid` gets set to 1 (a blue ?) and entity.`emoticoncooldown` gets set to 2.0 if all of the following conditions are met:
|
||||
|
||||
- We aren't in a `pause` or `minipause`
|
||||
- The [message](../../../SetText/Notable%20states.md#message) lock is released
|
||||
- The player isn't `digging`, `flying`, `startdig` or in `shield`
|
||||
|
||||
@@ -10,7 +10,7 @@ This interaction is heavily involved in the building of the shop structure. See
|
||||
- `buy`: The input string will be overriden to `dialogues[6].y` (the shop keeper's buying [dialogue line id](../../../SetText/Common%20commands%20id%20schemes/Dialogue%20line%20id.md)) and the parent becomes the `shopkeeper` transform. This only happens during the course of a [Shop](Shop.md) interaction, but not in this interaction.
|
||||
|
||||
## SetUp
|
||||
If `dialogues[10].x` floored is 1 (this is a medal shop), [SetBadgeShop](../Notable%20methods/SetBadgeShop.md) is called.
|
||||
If `dialogues[10].x` floored is 1 (this is a medal shop), SetBadgeShop(false) is called. For more information, check the [shop system](../Shop%20system.md) documentation
|
||||
|
||||
## Interact
|
||||
The same as [talk](Talk.md), but the input string of the [SetText](../../../SetText/SetText.md) call is the one resolved from `dialogues[0].y` as the [dialogue line id](../../../SetText/Common%20commands%20id%20schemes/Dialogue%20line%20id.md) which is shop keeper's selling line (or `dialogues[6].y` which is the buying one if `args` is `buy`).
|
||||
|
||||
@@ -5,10 +5,11 @@ The same than [Talk](Talk.md), but the [SetText](../../../SetText/SetText.md) in
|
||||
None.
|
||||
|
||||
## LateUpdate (Not a `dummy` and the entity is `incamera`)
|
||||
If the [message](../../SetText/Notable%20states.md#message) lock is released, we aren't `inevent` and it's not an [item entity](../../EntityControl/Item%20entity.md), the entity.[animstate](../EntityControl/Animations/animstate.md) is set to entity.`basestate`.
|
||||
If the [message](../../../SetText/Notable%20states.md#message) lock is released, we aren't `inevent` and it's not an [item entity](../../EntityControl/Item%20entity.md), the entity.[animstate](../../EntityControl/Animations/animstate.md) is set to entity.`basestate`.
|
||||
|
||||
## Interact
|
||||
The same than [Talk](Talk.md), but with a few changes:
|
||||
|
||||
- [flag](../../../Flags%20arrays/flags.md) slot 349 is set to true (using the storage service, allows multiselect)
|
||||
- The text used to call [SetText](../../../SetText/SetText.md) is `commondialogue[1]` (the Ant Storage Service text) unless [flag](../../../Flags%20arrays/flags.md) 180 (received the Ant Storage Service tutorial) is false. If it is false, the text is `|`[anim](../../../SetText/Individual%20commands/Anim.md)`,caller,Happy|` followed by `commondialogue[97]` (the Ant Storage Service tutorial).
|
||||
- [flag](../../../Flags%20arrays/flags.md) 180 (received the Ant Storage Service tutorial) is set to true. This ensures the tutorial isn't given again if it was.
|
||||
|
||||
@@ -5,7 +5,8 @@ Calls [SetText](../../../SetText/SetText.md) in [Dialogue mode](../../../SetText
|
||||
None.
|
||||
|
||||
## Interact
|
||||
Calls [SetText](../../../SetText/SetText.md) in [dialogue mode](../../../SetText/Dialogue%20mode.md) with the input string being the current one obtained with [GetDialogue](../GetDialogue.md):
|
||||
Calls [SetText](../../../SetText/SetText.md) in [dialogue mode](../../../SetText/Dialogue%20mode.md) with the input string being the current one obtained with [GetDialogue](../Notable%20methods/GetDialogue.md):
|
||||
|
||||
- The [fonttype](../../../SetText/Notable%20states.md#fonttype) is `BubblegumSans`
|
||||
- The default `messagebreak` is used as the linebreak
|
||||
- No tridimensional
|
||||
@@ -24,6 +25,7 @@ TODO: Need to revisit this when MapControl docs is done
|
||||
|
||||
## PlayerControl.LateUpdate
|
||||
entity.`emoticonid` gets set to 0 (the chatting icon) and entity.`emoticoncooldown` gets set to 2.0 if all of the following conditions are met:
|
||||
|
||||
- We aren't in a `pause` or `minipause`
|
||||
- The [message](../../../SetText/Notable%20states.md#message) lock is released
|
||||
- The player isn't `digging`, `flying`, `startdig` or in `shield`
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
# LateUpdate
|
||||
The logic depends on the [NPCType](NPCType.md), [ObjectTypes](ObjectTypes.md), [ActionBehaviors](ActionBehaviors.md) and [Interaction](Interaction.md). Consult each's documentation to learn more.
|
||||
The logic depends on the [NPCType](NPCType.md), [ObjectTypes](Object.md#objecttypes), [ActionBehaviors](ActionBehaviors.md) and [Interaction](Interaction.md). Consult each's documentation to learn more.
|
||||
|
||||
There are mainly 2 sections to this LateUpdate:
|
||||
|
||||
- A handler to a NaN position
|
||||
- The main logic when it's not a `dummy`
|
||||
|
||||
@@ -16,6 +17,7 @@ Some specific logic happens if we are `trapped` related to the [CoiledObject](Ob
|
||||
This section starts with the [NPC](NPCType.md#NPC) NPCType exclusive logic involving the `insideid` and whether or not the entity.`rigid` should be locked or unlocked. Consult the corresponding NPCType [section](NPC.md#lateupdate-non-dummy) to learn more.
|
||||
|
||||
After this whole logic, the rest of this section only happens if the entity is `incamera`. From there, there are several logic that occurs conditionally:
|
||||
|
||||
- The `pusher` enablement and center are updated when applicable, see the [NPCType enum table](NPCType.md#enum-table) to learn more.
|
||||
- If `startlife` is less than 300.0, it is incremented by framestep.
|
||||
- Some [WanderOffscreen](ActionBehaviors/WanderOffscreen.md) exclusive logic occurs here when applicable
|
||||
@@ -32,11 +34,12 @@ After this whole logic, the rest of this section only happens if the entity is `
|
||||
- Some [Shop](Interaction/Shop.md) and [CaravanBadge](Interaction/CaravanBadge.md) exclusive logic occurs here when applicable
|
||||
- Some [Geizer](ObjectTypes/Geizer.md) exclusive logic occurs here when applicable
|
||||
- If the entity `iskill` is false:
|
||||
- If the y position is less than the map.`ylimit`, then the position is set to the entity.`startpos`. On top of this, DeathSmoke particles are played at the entity.`sprite` position if the entity is `incamera`, it isn't `dead` and the [animid](../../Enums%20and%20IDs/AnimIDs.md) isn't negative (it isn't `None`). An exception to this logic is if it's a [Dropplet](ObjectTypes/Dropplet.md) object
|
||||
- Some [WanderOnWater](ActionBehaviors/WanderOnWater.md) and [ChaseOnWater](ActionBehaviors/ChaseOnWater.md) exclusive logic occurs here when applicable
|
||||
- If the y position is less than the map.`ylimit`, then the position is set to the entity.`startpos`. On top of this, DeathSmoke particles are played at the entity.`sprite` position if the entity is `incamera`, it isn't `dead` and the [animid](../../Enums%20and%20IDs/AnimIDs.md) isn't negative (it isn't `None`). An exception to this logic is if it's a [Dropplet](ObjectTypes/Dropplet.md) object
|
||||
- Some [WanderOnWater](ActionBehaviors/WanderOnWater.md) and [ChaseOnWater](ActionBehaviors/ChaseOnWater.md) exclusive logic occurs here when applicable
|
||||
|
||||
### Every 3 frames
|
||||
RefreshPlayer (see the section below for details) is called if the entity is `incamera` or the map.`limitbehavior` is false and all of the following are true:
|
||||
|
||||
- We aren't `inevent`
|
||||
- We aren't in a `minipause`
|
||||
- The `insideid` matches the current one
|
||||
@@ -49,6 +52,7 @@ If this is an [NPC](NPC.md), the emotes system updates occurs here, check the [N
|
||||
The entity.`ccol` height is set to `colliderheight` and its center is set to (0.0, half of `colliderheight`, 0.0) if this isn't the player's [beemerang](ObjectTypes/Beemerang.md) and the entity.`ccol` height isn't exactly the `colliderheight`.
|
||||
|
||||
If the entity `iskill` and the y position is above -999.0:
|
||||
|
||||
- The entity.`rigid` has its gravity disabled
|
||||
- The entity.`ccol` is disabled
|
||||
- The `boxcol` is disabled if it is present
|
||||
|
||||
@@ -15,19 +15,21 @@ For every 3 frames, if the entity is in a [forcemove](../EntityControl/EntityCon
|
||||
We decides if we should lock/unlock the entity `rigid` and call [StopForceMove](../EntityControl/EntityControl%20Methods.md#StopForceMove) only when the entity isn't `dead`, `iskill`, `deathcoroutine` isn't in progress and `activeonpause` is false.
|
||||
|
||||
It depends on `inevent` and whether or not the `insideid` matches the current one:
|
||||
|
||||
- If we aren't `inevent`:
|
||||
- If the `originalid` isn't -1 (the [animid](../../Enums%20and%20IDs/AnimIDs.md) isn't `None`), we ensure the entity `rigid` is locked via [LockRigid](../EntityControl/EntityControl%20Methods.md#lockrigid) if the `insideid` doesn't match the current one and unlocked if it does match. This is only performed when the current value of the entity `rigid.isKinematic` doesn't match the reality of the `insideid` matches or not.
|
||||
- If entity is in a `forcemove` and the `insideid` doesn't match the current one, [StopForceMove](../EntityControl/EntityControl%20Methods.md#StopForceMove) is called
|
||||
- If the `originalid` isn't -1 (the [animid](../../Enums%20and%20IDs/AnimIDs.md) isn't `None`), we ensure the entity `rigid` is locked via [LockRigid](../EntityControl/EntityControl%20Methods.md#lockrigid) if the `insideid` doesn't match the current one and unlocked if it does match. This is only performed when the current value of the entity `rigid.isKinematic` doesn't match the reality of the `insideid` matches or not.
|
||||
- If entity is in a `forcemove` and the `insideid` doesn't match the current one, [StopForceMove](../EntityControl/EntityControl%20Methods.md#StopForceMove) is called
|
||||
- If we are:
|
||||
- If the entity isn't a `fixedentity`, the `originalid` isn't -1 (the [animid](../../Enums%20and%20IDs/AnimIDs.md) isn't `None`) and it's not in a `forcemove`, [LockRigid(false, false)](../EntityControl/EntityControl%20Methods.md#lockrigid) is called if the `insideid` matches the current one
|
||||
- Otherwise, [StopForceMove](../EntityControl/EntityControl%20Methods.md#StopForceMove) is called instead
|
||||
- If the entity isn't a `fixedentity`, the `originalid` isn't -1 (the [animid](../../Enums%20and%20IDs/AnimIDs.md) isn't `None`) and it's not in a `forcemove`, [LockRigid(false, false)](../EntityControl/EntityControl%20Methods.md#lockrigid) is called if the `insideid` matches the current one
|
||||
- Otherwise, [StopForceMove](../EntityControl/EntityControl%20Methods.md#StopForceMove) is called instead
|
||||
|
||||
## OnTriggerEnter
|
||||
Only 2 things are handled here: the `specialinteract` if it's not `None` and some handling for the [StealthAI](ActionBehaviors/StealthAI.md) behavior.
|
||||
|
||||
The `specialinteract` part does the following if the other collider tag is `BeetleDash` (or `BeetleHorn` if the `specialinteract` is `AnyHorn`):
|
||||
|
||||
- Set `interactedwithhit` to true
|
||||
- Calls [Interact](Interact.md) with null arguments
|
||||
- Calls [Interact](Notable%20methods/Interact.md) with null arguments
|
||||
- Set `interactedwithhit` to false in 1 second
|
||||
|
||||
As for the `StealthAI` part, check its documentation to learn more.
|
||||
@@ -1,9 +1,10 @@
|
||||
# NPCControl
|
||||
NPCControl is a component that defines the behaviors of any map [Entities](../Entity.md). This only includes entities loaded from [map entity data](../../TextAsset%20Data/Entity%20data.md#map-entity-data) and all entities created for the purpose of a [shop system](Shop%20system.md). Its name is a missnomer because it doesn't just manage NPCs, but also objects and enemies so it should be viewed as "MapEntityControl".
|
||||
|
||||
Unlike [EntityControl](../EntityControl/EntityControl.md), this component exposes very little to be accessed externally with some exceptions, but most of these exceptions covers very narrow cases such as simply loading the field when map loading happens. One notable exception is [Interact](Interact.md) which offers the ability to provoke an interaction with the NPCControl.
|
||||
Unlike [EntityControl](../EntityControl/EntityControl.md), this component exposes very little to be accessed externally with some exceptions, but most of these exceptions covers very narrow cases such as simply loading the field when map loading happens. One notable exception is [Interact](Notable%20methods/Interact.md) which offers the ability to provoke an interaction with the NPCControl.
|
||||
|
||||
Most of this component's logic is into its startup, update and colliders handling lifecycle. It is mainly dictated by 4 elements:
|
||||
|
||||
- The [NPCType](NPCType.md)
|
||||
- The [ObjectTypes](Object.md#objecttypes) (when the NPCType is [Object](Object.md))
|
||||
- The default and `inrange` [ActionBehaviors](ActionBehaviors.md)
|
||||
|
||||
@@ -3,6 +3,7 @@ This is an enum that dictates the main capabilities of an NPCControl using the `
|
||||
|
||||
## Enum table
|
||||
The following tables includes different columns to better illustrate the main properties differences between the different enum value:
|
||||
|
||||
- Tag: The gameObject tag assigned on Start
|
||||
- Behaviors?: Whether or not [ActionBehaviors](ActionBehaviors.md) are enabled
|
||||
- Dialogues?: Whether or not [GetDialogue](Notable%20methods/GetDialogue.md) gets called which initialises a standard system to have the NPCControl call [SetText](../../SetText/SetText.md) conditionally with the lines coming from the `dialogues` field.
|
||||
@@ -12,14 +13,14 @@ The following tables includes different columns to better illustrate the main pr
|
||||
- `scol`: The state of the `scol` which is a trigger SphereCollider NPCControl manages.
|
||||
- `pusher`: The state of the `pusher` which is a trigger CapsuleCollider with a height twice the `ccol` and a raidus of twice as narrow. This is specifically present to have the player be pushed away if they collide with it. Its enablement is updated in LateUpdate while `dummy` is false and entity.`incamera` is true which keeps it enabled as long as we aren't `inevent`, [message](../../SetText/Notable%20states.md#message) is released and we aren't in a `minipause`, it is disabled otherwise. LateUpdate also ensures its center is set to (0.0, `colliderheight` + the entity `height`, 0.0).
|
||||
- `rigid` mass: The mass of the entity.`rigid`.
|
||||
- Far fading?: This is some logic in LateUpdate when `dummy` is false and entity.`incamera` is true where it will slightly fade out NPCControl too far away from the camera and fade them back in when getting close enough again. The logic adjusts the alpha of the `sprite` so that it is a lerp from the existing one to either 1.0 (opaque) or 0.3 (30% visible) with a factor of a 1/10 of the game's frametime. This fades in the entity or fades it out and what determines this is the entity `compos.z`: if it's 2.5 or above, we are fading in and fading out otherwise. The specific logic happens if all of the following are true:
|
||||
- `startlife` is above 20.0
|
||||
- The entity [animid](../../Enums%20and%20IDs/AnimIDs.md) isn't `None`
|
||||
- There is no `model`
|
||||
- The `sprite` is present
|
||||
- It's not a `hologram`
|
||||
- The current `insideid` matches this entity
|
||||
TODO: interesting, but unsure if it works because EntityControl also manages this
|
||||
- Far fading?: This is some logic in LateUpdate when `dummy` is false and entity.`incamera` is true where it will slightly fade out NPCControl too far away from the camera and fade them back in when getting close enough again. The logic adjusts the alpha of the `sprite` so that it is a lerp from the existing one to either 1.0 (opaque) or 0.3 (30% visible) with a factor of a 1/10 of the game's frametime. This fades in the entity or fades it out and what determines this is the entity `compos.z`: if it's 2.5 or above, we are fading in and fading out otherwise (
|
||||
TODO: unsure if it works because EntityControl also seems to manage this). The specific logic happens if all of the following are true:
|
||||
- `startlife` is above 20.0
|
||||
- The entity [animid](../../Enums%20and%20IDs/AnimIDs.md) isn't `None`
|
||||
- There is no `model`
|
||||
- The `sprite` is present
|
||||
- It's not a `hologram`
|
||||
- The current `insideid` matches this entity
|
||||
|
||||
|Value|Name|Tag|Behaviors?|Dialogues?|Interaction?|Emotes?|entity.`ccol`|`scol`|`pusher`|entity.`rigid`.mass<sup>1</sup>|Far fading?|
|
||||
|----:|----|---|----------|---------|------------|-------|------|------|--------|-----------------------|-----------|
|
||||
@@ -35,13 +36,15 @@ TODO: interesting, but unsure if it works because EntityControl also manages thi
|
||||
3: The `scol` is disabled if it's an [item entity](../EntityControl/Item%20entity.md) (which is always the case in practice for a `SemiNPC`). Also, it is left to null (not even added as a component) if it's The player [Beemerang](ObjectTypes/Beemerang.md).
|
||||
|
||||
4: Exceptions applies where the `ccol` remains enabled depending on `objecttype`:
|
||||
|
||||
- [SavePoint](ObjectTypes/SavePoint.md)
|
||||
- [RollingRock](ObjectTypes/RollingRock.md)
|
||||
- [FixedAnim](ObjectTypes/FixedAnim.md) (managed by a data field)
|
||||
- [Item](ObjectTypes/Item.md)
|
||||
- The player [Beemerang](ObjectTypes/Beemerang.md) (only remains enabled if the entity `fixedentity` is false)
|
||||
|
||||
5: These features are excluded for any of the following cases (Behaviors are always enabled, but [SetInitialBehavior](SetInitialBehavior.md) is not called under these cases):
|
||||
5: These features are excluded for any of the following cases (Behaviors are always enabled, but [SetInitialBehavior](Notable%20methods/SetInitialBehavior.md) is not called under these cases):
|
||||
|
||||
- This is an [item entity](../EntityControl/Item%20entity.md). This is always the case in practice for a `SemiNPC` meaning behaviors don't actually do anything useful on them
|
||||
- entity.[animid](../../Enums%20and%20IDs/AnimIDs.md) is negative
|
||||
- `interacttype` is [Shop](Interaction/Shop.md) or [CaravanBadge](Interaction/CaravanBadge.md)
|
||||
|
||||
@@ -5,8 +5,9 @@ This does nothing if `alwaysemoticon` is false, the y distance between this and
|
||||
|
||||
If we are doing something, we try to find the first `emoticonflag` that is applicable.
|
||||
|
||||
The way it works is NPCControl has a general purpose Vector2 array field called `emoticonflag` which contains for each element data an emoticon id and a [flag](../../Flags%20arrays/flags.md) slot required to have it applied. The flag slot checks are performed in reverse order from the list, but one is always picked meaning the first one in the array serves as a falback. Here is how the components are defined (NOTE: despite all components being float, each gets cast to int for this which truncates the fractional part):
|
||||
- x: A required [flag](../../Flags%20arrays/flags.md) slot to be true in order for the line to be set as the current one. This is always violated if it's negative.
|
||||
The way it works is NPCControl has a general purpose Vector2 array field called `emoticonflag` which contains for each element data an emoticon id and a [flag](../../../Flags%20arrays/flags.md) slot required to have it applied. The flag slot checks are performed in reverse order from the list, but one is always picked meaning the first one in the array serves as a falback. Here is how the components are defined (NOTE: despite all components being float, each gets cast to int for this which truncates the fractional part):
|
||||
|
||||
- x: A required [flag](../../../Flags%20arrays/flags.md) slot to be true in order for the line to be set as the current one. This is always violated if it's negative.
|
||||
- y: The emoticon id related to this element
|
||||
|
||||
When the method finds the first element whose x's condition is satisfied in reverse order (or the first one if it got to it), it sets the entity `emoticonid` to the y component and `emoticoncooldown` to 5.0.
|
||||
@@ -6,31 +6,31 @@ This is a public method that initialises `descwindow`. It is called both by the
|
||||
- `deswindow` is set to the DialogueAnim of a new white 9Box using `Sprites/GUI/9Box/box0` of position (-3.5.0, -3.9.0, 10.0) with size (11.0, 3.0) with sortingOrder of -3 and with growing
|
||||
- If it was called from CheckItem, instance.`showmoney` is set to 0.0 which hides the berry count HUD element followed by the `descwindow` local position being set to (0.0, the existing y local position - 0.5, the existing z local position)
|
||||
- If the `shopkeeper` exists and its `dialgues[1].y` is 1 (the shop accepts Crystal Berries instead of regular berries):
|
||||
- A new SpriteRenderer UI object named `CBerryBar` is created childed to the `descwindow` of color cyan with position (10.65, -0.45, 0.0) with size (0.55, 0.6, 1.0) with `guisprites[4]` (the HUD element background) and a sortingOrder of 0
|
||||
- [SetText](../../../SetText/SetText.md) is called using `|sort,10||color,4||single||dropshadow,0.75,-0.75|` followed by [flagvar](../../../Flags%20arrays/flagvar.md) 14 padded by 3 `0` as the input string in [non dialogue mode](../../../SetText/Dialogue%20mode.md#non-dialogue-mode) with the following:
|
||||
- [fonttype](../../../SetText/Notable%20states.md#fonttype) of 2 (gets overriden to `D3Streetism` as 2 is UNUSED)
|
||||
- No linebreak
|
||||
- No tridimensional
|
||||
- Position offset of (-0.65, -0.5, 0.0)
|
||||
- No camera offset
|
||||
- size of 1.75 uniform
|
||||
- Parent is the SpriteRenderer created earlier
|
||||
- No caller
|
||||
- A new UI object called `BerryIcon` is created using the sprite of the Crystal Berry icon childed to the `descwindow` with a position of (9.45, -0.45, 0.0) with a size of Vector3.one and a sortingOrder of 1
|
||||
- A new SpriteRenderer UI object named `CBerryBar` is created childed to the `descwindow` of color cyan with position (10.65, -0.45, 0.0) with size (0.55, 0.6, 1.0) with `guisprites[4]` (the HUD element background) and a sortingOrder of 0
|
||||
- [SetText](../../../SetText/SetText.md) is called using `|sort,10||color,4||single||dropshadow,0.75,-0.75|` followed by [flagvar](../../../Flags%20arrays/flagvar.md) 14 padded by 3 `0` as the input string in [non dialogue mode](../../../SetText/Dialogue%20mode.md#non-dialogue-mode) with the following:
|
||||
- [fonttype](../../../SetText/Notable%20states.md#fonttype) of 2 (gets overriden to `D3Streetism` as 2 is UNUSED)
|
||||
- No linebreak
|
||||
- No tridimensional
|
||||
- Position offset of (-0.65, -0.5, 0.0)
|
||||
- No camera offset
|
||||
- size of 1.75 uniform
|
||||
- Parent is the SpriteRenderer created earlier
|
||||
- No caller
|
||||
- A new UI object called `BerryIcon` is created using the sprite of the Crystal Berry icon childed to the `descwindow` with a position of (9.45, -0.45, 0.0) with a size of Vector3.one and a sortingOrder of 1
|
||||
- If entity.`animid` is 2 (it's a [medal](../../../Enums%20and%20IDs/Medal.md)), [flagvar](../../../Flags%20arrays/flagvar.md) 10 is set to the price of the medal (entity.`animstate` used as the id, berries or Crystal Berries depending on `shopkeeper.dialogues[1].y` being 1 or not), but it's overriden to 35 berries (or 4 Crystal Berries unless [flagvar](../../../Flags%20arrays/flagvar.md) 66 (amount of medals bought at shades) is less than 2 where it's 3 Crystal Berries) if the `shopkeeper` exists and [flag](../../../Flags%20arrays/flags.md) 681 is true (MYSTERY? is active)
|
||||
- Otherwise, [flagvar](../../../Flags%20arrays/flagvar.md) 10 is set to the buying price of the [item](../../../Enums%20and%20IDs/Items.md) * `mmulti` (the price multiplier loaded from the shop keeper entity data) all ceiled
|
||||
- From there, a SetText string is constructed with the following appended together in order:
|
||||
- `|single||singlebreak,` followed by `itemdescbreak` followed by `|`
|
||||
- If entity.`animid` is 2 (it's a medal) and the call came from the [Shop](../Interaction/Shop.md) interaction, the name of the medal is appended (overriden to `menutext[59]` or `?????` if MYSTERY? is active) followed by ` ` followed by a `-` (or a `—` if the [languageid](../../../SetText/languageid.md) is `German`) followed by ` ` followed by `menutext[49]` (`Worth |currency,var,10|`) if `shopkeeper.dialogues[1].y` isn't 1 (the shop accepts regular berries) and if it's 1, it's followed by `flagvar` 10 followed by a space followed by `menutext[169]` (Crystal Berries, it's `menutext[112]` if `flagvar` 10 is 1 for the singular form) followed by `|line|`
|
||||
- If entity.`animid` is 2 (it's a medal), the description of the medal is appened (entity.`animstate` is used as the medal id), but it's overriden to `menutext[59]` (`?????`) if the `shopkeeper` exists and MYSTERY? is active
|
||||
- If entity.`animid` isn't 2 (it's not a medal) and the call came from the [Shop](../Interaction/Shop.md) interaction, the name of the [item](../../../Enums%20and%20IDs/Items.md) is appended (entity.`animstate` is used as the item id) followed by ` ` followed by ` ` followed by a `-` (or a `—` if the [languageid](../../../SetText/languageid.md) is `German`) followed by ` ` followed by `menutext[49]` (`Worth |currency,var,10|`) followed by `|line|`
|
||||
- If entity.`animid` isn't 2 (it's not a medal), the description of the item is appended (entity.`animstate` is used as the item id)
|
||||
- `|single||singlebreak,` followed by `itemdescbreak` followed by `|`
|
||||
- If entity.`animid` is 2 (it's a medal) and the call came from the [Shop](../Interaction/Shop.md) interaction, the name of the medal is appended (overriden to `menutext[59]` or `?????` if MYSTERY? is active) followed by ` ` followed by a `-` (or a `—` if the [languageid](../../../SetText/languageid.md) is `German`) followed by ` ` followed by `menutext[49]` (`Worth |currency,var,10|`) if `shopkeeper.dialogues[1].y` isn't 1 (the shop accepts regular berries) and if it's 1, it's followed by `flagvar` 10 followed by a space followed by `menutext[169]` (Crystal Berries, it's `menutext[112]` if `flagvar` 10 is 1 for the singular form) followed by `|line|`
|
||||
- If entity.`animid` is 2 (it's a medal), the description of the medal is appened (entity.`animstate` is used as the medal id), but it's overriden to `menutext[59]` (`?????`) if the `shopkeeper` exists and MYSTERY? is active
|
||||
- If entity.`animid` isn't 2 (it's not a medal) and the call came from the [Shop](../Interaction/Shop.md) interaction, the name of the [item](../../../Enums%20and%20IDs/Items.md) is appended (entity.`animstate` is used as the item id) followed by ` ` followed by ` ` followed by a `-` (or a `—` if the [languageid](../../../SetText/languageid.md) is `German`) followed by ` ` followed by `menutext[49]` (`Worth |currency,var,10|`) followed by `|line|`
|
||||
- If entity.`animid` isn't 2 (it's not a medal), the description of the item is appended (entity.`animstate` is used as the item id)
|
||||
- A SetText call occurs in [non dialogue mode](../../../SetText/Dialogue%20mode.md#non-dialogue-mode) with the string generated above with these properties:
|
||||
- [fonttype](../../../SetText/Notable%20states.md#fonttype) of `BubblegumSans`
|
||||
- No linebreak
|
||||
- No tridimensional
|
||||
- Position offset of (-5.2, 0.65, 0.0)
|
||||
- No camera offset
|
||||
- size of 0.675 uniform
|
||||
- Parent is the `descwindow`
|
||||
- No caller
|
||||
- [fonttype](../../../SetText/Notable%20states.md#fonttype) of `BubblegumSans`
|
||||
- No linebreak
|
||||
- No tridimensional
|
||||
- Position offset of (-5.2, 0.65, 0.0)
|
||||
- No camera offset
|
||||
- size of 0.675 uniform
|
||||
- Parent is the `descwindow`
|
||||
- No caller
|
||||
@@ -3,23 +3,24 @@ Dizzy is a coroutine that performs the procedure done whenever an [Enemy](../Ene
|
||||
|
||||
A yield break is performed immediately if the entity is `dead`, `iskill` or it has a `deathcoroutine` in progress.
|
||||
|
||||
First, [LockRigid(false)](../EntityControl/EntityControl%20Methods.md#lockrigid) is called on the entity which unlocks its `rigid`.
|
||||
First, [LockRigid(false)](../../EntityControl/EntityControl%20Methods.md#lockrigid) is called on the entity which unlocks its `rigid`.
|
||||
|
||||
The `disguiseobj` is disabled if it exists with the entity.`sprite` getting enabled.
|
||||
|
||||
From there, there's a special case if the entity's `originalid` is the `ToeBiter` [animid](../../Enums%20and%20IDs/AnimIDs.md) where if the `internaltransform[0]` is present (the boulder he throws), it needs to be setup for its destruction. This is first done by adding a RigidBody to it, make it go in a random direction of 3.0 magnitude at a height of 12.0 and destroying it in 3.0 seconds. The entire `internaltransform` array is then set to null.
|
||||
From there, there's a special case if the entity's `originalid` is the `ToeBiter` [animid](../../../Enums%20and%20IDs/AnimIDs.md) where if the `internaltransform[0]` is present (the boulder he throws), it needs to be setup for its destruction. This is first done by adding a RigidBody to it, make it go in a random direction of 3.0 magnitude at a height of 12.0 and destroying it in 3.0 seconds. The entire `internaltransform` array is then set to null.
|
||||
|
||||
From there, a couple of adjustements happens:
|
||||
|
||||
- The `touchcooldown` is set to 30.0 frames
|
||||
- The `dizzytime` is to the sent time parameter
|
||||
- The entity.`sprite` has its angles reset to Vector3.zero
|
||||
- The entity.`onground` is set to false
|
||||
- STOP is called which does the following:
|
||||
- Stop `behaviorroutine` if it was in progress and set it to null
|
||||
- Set `forcebehavior` to null and call [StopForceBehavior](StopForceBehavior.md)
|
||||
- Call [StopForceMove](../EntityControl/EntityControl%20Methods.md#StopForceMove) on the entity
|
||||
- Set the entity.`overrideflip` and entity.`overrideonlyflip` to false
|
||||
- Set `attacking` to false
|
||||
- Stop `behaviorroutine` if it was in progress and set it to null
|
||||
- Set `forcebehavior` to null and call [StopForceBehavior](StopForceBehavior.md)
|
||||
- Call [StopForceMove](../../EntityControl/EntityControl%20Methods.md#stopforcemove) on the entity
|
||||
- Set the entity.`overrideflip` and entity.`overrideonlyflip` to false
|
||||
- Set `attacking` to false
|
||||
|
||||
After, a frame is yielded.
|
||||
|
||||
@@ -27,9 +28,10 @@ If the enemy has an [Unmoveable](../ActionBehaviors/Unmoveable.md) behavior, it
|
||||
|
||||
## Not Unmovable
|
||||
If it doesn't have this behavior however, the rest of the logic is performed:
|
||||
|
||||
- Set `ignoreconstraint` to true
|
||||
- Enable gravity on the entity.`rigid` without kinematic
|
||||
- If the entity didn't had a `detect`, [CreateDetector](../EntityControl/EntityControl%20Methods.md#CreateDetector) is called to create it
|
||||
- If the entity didn't had a `detect`, [CreateDetector](../../EntityControl/EntityControl%20Methods.md#createdetector) is called to create it
|
||||
- The entity.`detect` is set to look at the player and its y angle is multiplied by -1
|
||||
- The entity.`hitwal` is set to false
|
||||
- All rotation on the entity.`rigid` are frozen
|
||||
@@ -39,4 +41,4 @@ If it doesn't have this behavior however, the rest of the logic is performed:
|
||||
|
||||
After, the `hitpart` particle is played at the entity.`sprite` position + (0.0, 0.5, 0.0) and a frame is yield.
|
||||
|
||||
Finally, if the entity.`rigid` y velocity is less than 5.0, [Jump](../EntityControl/EntityControl%20Methods.md#jump) is called on the entity with a velocity of 13.5 for every frame as until the entity.`rigid` y velocity reaches 5.0 or above.
|
||||
Finally, if the entity.`rigid` y velocity is less than 5.0, [Jump](../../EntityControl/EntityControl%20Methods.md#jump) is called on the entity with a velocity of 13.5 for every frame as until the entity.`rigid` y velocity reaches 5.0 or above.
|
||||
@@ -1,5 +1,5 @@
|
||||
# DoBehaviour
|
||||
This is a method that takes in an [ActionBehaviors](../ActionBehaviors.md) (as ref which allows to override it) and the corresponding frequency which despite its name serve as a general float argument. It is only called as part of the [Update](Update.md) event and it is responsible for setting up and executing the applicable behavior.
|
||||
This is a method that takes in an [ActionBehaviors](../ActionBehaviors.md) (as ref which allows to override it) and the corresponding frequency which despite its name serve as a general float argument. It is only called as part of the [Update](../Update.md) event and it is responsible for setting up and executing the applicable behavior.
|
||||
|
||||
## Before behavior execution
|
||||
Some disguise behavior specific logic occurs here. See [Disguise section](../ActionBehaviors/Disguise.md#dobehavior-behavior-no-longer-exists) for more information.
|
||||
@@ -10,4 +10,4 @@ From there, the appropriate [ActionBehavior](../ActionBehaviors.md) occurs, chec
|
||||
## After behavior execution
|
||||
After the behavior logic, entity.`ccol` center is set to (0.0, entity.`ccol` height / 2.0, 0.0).
|
||||
|
||||
If the entity has a defined [animid](../../Enums%20and%20IDs/AnimIDs.md), it isn't an [item entity](../../EntityControl/Item%20entity.md) and it's not a `fixedentity`, the entity.`rigid` rotation gets frozen and on top of this, if it had zero velocity, all movement except the y ones are frozen too.
|
||||
If the entity has a defined [animid](../../../Enums%20and%20IDs/AnimIDs.md), it isn't an [item entity](../../EntityControl/Item%20entity.md) and it's not a `fixedentity`, the entity.`rigid` rotation gets frozen and on top of this, if it had zero velocity, all movement except the y ones are frozen too.
|
||||
@@ -1,18 +1,19 @@
|
||||
# GetDialogue
|
||||
This method not only returns the [SetText](../../SetText/SetText.md) line the [NPC](../NPC.md) has at the current moment, it also configures some fields that this line needs.
|
||||
This method not only returns the [SetText](../../../SetText/SetText.md) line the [NPC](../NPC.md) has at the current moment, it also configures some fields that this line needs.
|
||||
|
||||
## Normal process
|
||||
The way it works is NPCControl has a general purpose Vector3 field called `dialogues` which contains for each element data about a SetText line assigned to the entity. The order of the elements is important: the method will search for the first suitable one to set as current in reverse order (from last to first).
|
||||
|
||||
Here is how the components of an element are defined (NOTE: despite all components being float, each gets cast to int for this which truncates the fractional part):
|
||||
- x: A required [flag](../../Flags%20arrays/flags.md) slot to be true in order for the line to be set as the current one. If it's <= -1, it means no flag is required and the line will be set as the current one when encountered. If the condition is violated, the method will ignore this element and check the next one.
|
||||
- y: The [dialogue line id](../../SetText/Common%20commands%20id%20schemes/Dialogue%20line%20id.md) related to this element. Because it uses the same scheme SetText commands uses, it supports both map specific line id or common dialogue line id.
|
||||
- z: The `basestate` and `animstate` to set the entity when this line is set as the current one. The `basestate` is the default [animstate](../EntityControl/Animations/animstate.md) the entity has instead of the default which is `Idle` or 0. This allows to force the entity into a different animation when the line is selected as current.
|
||||
|
||||
- x: A required [flag](../../../Flags%20arrays/flags.md) slot to be true in order for the line to be set as the current one. If it's <= -1, it means no flag is required and the line will be set as the current one when encountered. If the condition is violated, the method will ignore this element and check the next one.
|
||||
- y: The [dialogue line id](../../../SetText/Common%20commands%20id%20schemes/Dialogue%20line%20id.md) related to this element. Because it uses the same scheme SetText commands uses, it supports both map specific line id or common dialogue line id.
|
||||
- z: The `basestate` and `animstate` to set the entity when this line is set as the current one. The `basestate` is the default [animstate](../../EntityControl/Animations/animstate.md) the entity has instead of the default which is `Idle` or 0. This allows to force the entity into a different animation when the line is selected as current.
|
||||
|
||||
When the method finds the first element whose x's condition is satisfied in reverse order, it sets `currentdialogueindex` to the element's index, the entity's `basestate` to the z component and it returns the actual SetText line corresponding to the y component.
|
||||
|
||||
## Override dialogue feature
|
||||
There is however an exception to this: it's possible to override this logic by setting `overridediag` to a non negative value which will be used as the [dialogue line id](../../SetText/Common%20commands%20id%20schemes/Dialogue%20line%20id.md) instead. This feature is never used under normal gameplay and this field's default value remains -1. It should be noted that this feature specifically supports the incomplete [global commands system](../../SetText/Related%20Systems/GlobalCommand.md) and it supports [SavePoint](../Interaction/SavePoint.md) interactions unlike the normal process.
|
||||
There is however an exception to this: it's possible to override this logic by setting `overridediag` to a non negative value which will be used as the [dialogue line id](../../../SetText/Common%20commands%20id%20schemes/Dialogue%20line%20id.md) instead. This feature is never used under normal gameplay and this field's default value remains -1. It should be noted that this feature specifically supports the incomplete [global commands system](../../../SetText/Related%20Systems/GlobalCommand.md) and it supports [SavePoint](../Interaction/SavePoint.md) interactions unlike the normal process.
|
||||
|
||||
## Error handling and exceptional cases
|
||||
If the `interacttype` is [Shop](../Interaction/Shop.md) or [SavePoint](../ObjectTypes/SavePoint.md) or none of the elements in `dialogues` field is suitable to set as current, no fields are touched and the return value is hardcoded to `|`[color](../../SetText/Individual%20commands/Color.md)`,1|Invalid message.`. This should never happen under normal gameplay because this is supposed to be a debug message that isn't supposed to be seen if every entities are correctly configured. This is only for diagnosis purposes.
|
||||
If the `interacttype` is [Shop](../Interaction/Shop.md) or [SavePoint](../ObjectTypes/SavePoint.md) or none of the elements in `dialogues` field is suitable to set as current, no fields are touched and the return value is hardcoded to `|`[color](../../../SetText/Individual%20commands/Color.md)`,1|Invalid message.`. This should never happen under normal gameplay because this is supposed to be a debug message that isn't supposed to be seen if every entities are correctly configured. This is only for diagnosis purposes.
|
||||
@@ -1,18 +1,19 @@
|
||||
TODO: It was never clear what was the ACTUAL issue that necessited this hacky workaround. More investigations should be done on why this was needed and if found, the proper fix should be documented because this can have unintended consequences.
|
||||
|
||||
# GravityFix
|
||||
This coroutine was made to workaround an issue where enemies could fall under the map. It messes with the entity.`rigid` and its position several times in rather intrusive ways. It always gets started at the end of [Start](Start.md) unless the `NGF` [Modifier](../../EntityControl/Modifiers.md) is enabled.
|
||||
This coroutine was made to workaround an issue where enemies could fall under the map. It messes with the entity.`rigid` and its position several times in rather intrusive ways. It always gets started at the end of [Start](../Start.md) unless the `NGF` [Modifier](../../EntityControl/Modifiers.md) is enabled.
|
||||
|
||||
Here are the steps performed in order:
|
||||
|
||||
- A frame is yeilded
|
||||
- The entity.`rigid`'s useGravity and isKinematic are saved temporarilly
|
||||
- A raycast from the current position + Vector3.up is done downwards of any layer of Ground and NoDigGround. If hit with a transform, this enemy's absolute y position is set to the y of that hit point
|
||||
- The current position is saved into a temporary variable
|
||||
- For a minimum of 1 second, the following is done every frame so long as `minipause` is true or that `hasenteredrange` is false:
|
||||
- The entity.`rigid` gravity is disabled and placed in kinematic mode without velocity
|
||||
- This enemies's position is set to the variable saved earlier
|
||||
- The entity.`rigid` gravity is disabled and placed in kinematic mode without velocity
|
||||
- This enemies's position is set to the variable saved earlier
|
||||
- For an additional 5 frames, the following is performed each frame:
|
||||
- The position is again set to the variable saved earlier
|
||||
- LatePos is called on this transform with the variable saved earlier using a 0.02 delay only trying once
|
||||
- The entity.`rigid` velocity is zeroed out
|
||||
- The position is again set to the variable saved earlier
|
||||
- LatePos is called on this transform with the variable saved earlier using a 0.02 delay only trying once
|
||||
- The entity.`rigid` velocity is zeroed out
|
||||
- Finally, the original values of the entity.`rigid`'s useGravity and useKinematic are restored
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
# HasHiddenItem
|
||||
This method tells if the NPCControl pertains to an item that is discoverable by the Detector [Medal](../../Enums%20and%20IDs/Medal.md). It only returns true if all of the following are true (it returns false otherwise):
|
||||
This method tells if the NPCControl pertains to an item that is discoverable by the Detector [Medal](../../../Enums%20and%20IDs/Medal.md). It only returns true if all of the following are true (it returns false otherwise):
|
||||
|
||||
- The `entitytype` is [Object](../Object.md)
|
||||
- The player has the Detector equipped
|
||||
- The `interacttype` isn't [CaravanBadge](../Interaction/CaravanBadge.md) or [Shop](../Interaction/Shop.md)
|
||||
- The `NDTCT` [Modifier](../../EntityControl/Modifiers.md) isn't enabled
|
||||
- Either the `DDIST` [Modifier](../EntityControl/Modifiers.md) isn't enabled or it is, but the player's z position is less than 20.0 away from this transform z position
|
||||
- Either the `DDIST` [Modifier](../../EntityControl/Modifiers.md) isn't enabled or it is, but the player's z position is less than 20.0 away from this transform z position
|
||||
- The `objecttype` must belong to a specific set on top of an additional condition for the method to return true. Consult each's documentation to learn more:
|
||||
- [BeetleGrass](../ObjectTypes/BeetleGrass.md)
|
||||
- [DigSpot](../ObjectTypes/DigSpot.md)
|
||||
- [Item](../ObjectTypes/Item.md)
|
||||
- [BeetleGrass](../ObjectTypes/BeetleGrass.md)
|
||||
- [DigSpot](../ObjectTypes/DigSpot.md)
|
||||
- [Item](../ObjectTypes/Item.md)
|
||||
|
||||
|
||||
@@ -4,8 +4,9 @@ This public method is one of the few that is fully intended to be called externa
|
||||
The method takes a string argument named `args`, but only a few `Interaction` uses it.
|
||||
|
||||
There is some common logic that precedes any `Interaction` specific logic and it goes as follows:
|
||||
- [StopForceMove](../EntityControl/EntityControl%20Methods.md#StopForceMove) is called on the entity
|
||||
- [StopMoving](../EntityControl/EntityControl%20Methods.md#StopMoving) is called on the player entity
|
||||
|
||||
- [StopForceMove](../../EntityControl/EntityControl%20Methods.md) is called on the entity
|
||||
- [StopMoving](../../EntityControl/EntityControl%20Methods.md#stopmoving) is called on the player entity
|
||||
- CancelAction is called on the player
|
||||
|
||||
After, the logic is specific to each `Interaction`. Consult each's documentation to learn more.
|
||||
@@ -9,13 +9,13 @@ This is a helper method to respawn an [Enemy](../NPCType.md#enemy) at a certain
|
||||
- entity.`spin` is zeroed out
|
||||
- entity.`rigid` gravity is enabled without kinematic and with the velocity zeroed out
|
||||
- entity.`sprite` is enabled and its angles set to zero
|
||||
- entity.[animstate](../EntityControl/Animations/animstate.md) is set to the `basestate`
|
||||
- entity.[animstate](../../EntityControl/Animations/animstate.md) is set to the `basestate`
|
||||
- entity.`overrideanim` is set to false
|
||||
- entity.`onground` is set to false
|
||||
- entity.`bobspeed` and entity.`bobrange` are reset to their start fields counterparts
|
||||
- entity.`lastpos` is set to the position passed as parameter
|
||||
- entity.`pausepos` is set to null unless we are `paused` in which case, it is also set to the passed position
|
||||
- [StopForceMove](../EntityControl/EntityControl%20Methods.md#StopForceMove) is called
|
||||
- [StopForceMove](../../EntityControl/EntityControl%20Methods.md#stopforcemove) is called
|
||||
- `dizzytime` is set to 0.0
|
||||
- `respawntimer` is set to -100.0
|
||||
- `freezecooldown` is set to 0.0
|
||||
@@ -24,6 +24,6 @@ This is a helper method to respawn an [Enemy](../NPCType.md#enemy) at a certain
|
||||
- `hit` is set to false
|
||||
- The position and the entity's `startpos` are set to the passed parameter
|
||||
- Some logic happens if the default behavior is a disguise one
|
||||
- [LockRigid(false)](../EntityControl/EntityControl%20Methods.md#LockRigid) is called on the entity which unlocks its `rigid`
|
||||
- [LockRigid(false)](../../EntityControl/EntityControl%20Methods.md#lockrigid) is called on the entity which unlocks its `rigid`
|
||||
- The `pusher` is enabled if it exist. NOTE: normally, enemies do not have one
|
||||
- DeathSmoke is called on the entity.`sprite`'s position
|
||||
@@ -1,4 +1,4 @@
|
||||
# SetInitialBehavior
|
||||
This method first applies a special case where for any `BeeGuard` [AnimId](../../Enums%20and%20IDs/AnimIDs.md), it overrides the `tattleid` to -97 (common [dialogue line id](../../SetText/Common%20commands%20id%20schemes/Dialogue%20line%20id.md) 96) if it had -1 already.
|
||||
This method first applies a special case where for any `BeeGuard` [AnimId](../../../Enums%20and%20IDs/AnimIDs.md), it overrides the `tattleid` to -97 (common [dialogue line id](../../../SetText/Common%20commands%20id%20schemes/Dialogue%20line%20id.md) 96) if it had -1 already.
|
||||
|
||||
Some specific logic are performoned depending on the default [ActionBehavior](../ActionBehaviors.md), check their documentation to learn more.
|
||||
@@ -4,7 +4,7 @@ This is a void and parameterless method in NPCControl (not to be confused with t
|
||||
The name is a bit missleading here: while it does take part in the start of an actual battle, it is not the method that starts it. That would be the coroutine of the same name in BattleControl which this does start one if all conditions are met. This method doesn't just setup the start of the battle, it also performas any logic needed the moment an enemy is engaged which may include not doing anything or even do something else instead of starting a battle.
|
||||
|
||||
## Bubble Shield logic
|
||||
If the player's `shield` is on and the entity's `originalid` isn't the `DeadLanderC` [animid](../../Enums%20and%20IDs/AnimIDs.md) (it cannot be stunned using Bubble Shield) then this logic applies. It will only do anything if the `touchcooldown` expired, otherwise, nothing happens.
|
||||
If the player's `shield` is on and the entity's `originalid` isn't the `DeadLanderC` [animid](../../../Enums%20and%20IDs/AnimIDs.md) (it cannot be stunned using Bubble Shield) then this logic applies. It will only do anything if the `touchcooldown` expired, otherwise, nothing happens.
|
||||
|
||||
If the `ShieldHit` audio clip isn't playing on any of the `sounds` audio sources, it is played on the first free one with 75% volume and a random pitch between 0.95 and 1.05. This is followed by a [Dizzy](Dizzy.md) call for 100.0 frames with a pushforce being the direction vector from this enemy to the player * 5.0 without vertical launch.
|
||||
|
||||
@@ -12,26 +12,29 @@ If the `ShieldHit` audio clip isn't playing on any of the `sounds` audio sources
|
||||
This section happens only if the Bubble Shield one didn't.
|
||||
|
||||
2 special early exits cases are handled:
|
||||
|
||||
- If we are already in a `battle` or we are in a `minipause`, this causes this method to return early
|
||||
- If `entitytouchevent` is 0 or above, the [event](../../Enums%20and%20IDs/Events.md) whose id is this field is started before returning early. This is essentially a global feature of the game that allows to override most engagement with an enemy to be an event start instead of a potential battle.
|
||||
- If `entitytouchevent` is 0 or above, the [event](../../../Enums%20and%20IDs/Events.md) whose id is this field is started before returning early. This is essentially a global feature of the game that allows to override most engagement with an enemy to be an event start instead of a potential battle.
|
||||
|
||||
If we haven't returned from this, the entity.`lastpost` is set to this enemy position and the entity.`rigid` velocity is zeroed out.
|
||||
|
||||
From there, 2 other early returns special cases are checked:
|
||||
|
||||
- If the `icooldown` of the player.entity hasn't expired yet or the enemy's `freezecooldown` hasn't expired yet or its entity is `dead` or its `touchcooldown` hasn't expired yet, this method will return early.
|
||||
- If the the Bug Me Not! [medal](../../Enums%20and%20IDs/Medal.md) applies, the entity is put in kinematic mode without velocity and a [Death(true)](../EntityControl/Notable%20methods/Death.md) coroutine is started on it. The logic to determine if the medal applies is as follows:
|
||||
- The played must have it equipped or it will not apply
|
||||
- If the [flag](../../Flags%20arrays/flags.md) slot 555 (post game) is true, the `partylevel` is exactly 27 and the current [map](../../Enums%20and%20IDs/Maps.md) isn't `GiantLairDeadLands1` or `GiantLairDeadLands2`, then it applies no matter what (NOTE: it implies the medal never works on these 2 maps because the case below excludes the area that includes them too)
|
||||
- Otherwise, it will only apply if the [area](../../Enums%20and%20IDs/librarystuff/Areas.md) isn't Giant's Lair, the map isn't `BugariaPlazaAttack`, `BugariaBridgeAttack` or `BugariaCastleAttack` and either the `partylevel` is exactly 27 or the ExpEstimate of this encounter is equal or less than the amount of enemies in this encounter
|
||||
- If the the Bug Me Not! [medal](../../../Enums%20and%20IDs/Medal.md) applies, the entity is put in kinematic mode without velocity and a [Death(true)](../../EntityControl/Notable%20methods/Death.md) coroutine is started on it. The logic to determine if the medal applies is as follows:
|
||||
- The played must have it equipped or it will not apply
|
||||
- If the [flag](../../../Flags%20arrays/flags.md) slot 555 (post game) is true, the `partylevel` is exactly 27 and the current [map](../../../Enums%20and%20IDs/Maps.md) isn't `GiantLairDeadLands1` or `GiantLairDeadLands2`, then it applies no matter what (NOTE: it implies the medal never works on these 2 maps because the case below excludes the area that includes them too)
|
||||
- Otherwise, it will only apply if the [area](../../../Enums%20and%20IDs/librarystuff/Areas.md) isn't Giant's Lair, the map isn't `BugariaPlazaAttack`, `BugariaBridgeAttack` or `BugariaCastleAttack` and either the `partylevel` is exactly 27 or the ExpEstimate of this encounter is equal or less than the amount of enemies in this encounter
|
||||
|
||||
If we still haven't returned, then a battle will occur and the rest is just to setup the StartBattle call.
|
||||
|
||||
All [EntityControl](../EntityControl/EntityControl.md) will have their `lastpos` set to their current positions. Then, CancelAction is called on the player and the enemy's entity.`spin` is zeroed out. `attacking` is set to false and finally, [StopForceBehavior](StopForceBehavior.md) is called.
|
||||
All [EntityControl](../../EntityControl/EntityControl.md) will have their `lastpos` set to their current positions. Then, CancelAction is called on the player and the enemy's entity.`spin` is zeroed out. `attacking` is set to false and finally, [StopForceBehavior](StopForceBehavior.md) is called.
|
||||
|
||||
The last step is the actual StartBattle call:
|
||||
|
||||
- The enemies list is `battleids`
|
||||
- Automatically determine the battle map
|
||||
- No specific advantage except if `attacking` was true when this was called and the `dizzytime` expired while the player doesn't have the Crazy Prepared [medal](../../Enums%20and%20IDs/Medal.md) equipped. In that case, it will be set to 3 with the `Damage0` sound playing
|
||||
- No specific advantage except if `attacking` was true when this was called and the `dizzytime` expired while the player doesn't have the Crazy Prepared [medal](../../../Enums%20and%20IDs/Medal.md) equipped. In that case, it will be set to 3 with the `Damage0` sound playing
|
||||
- The music is automatically determined unless the enemies list contains a `WaspTrooper`, `WaspBomber`, `WaspDriller` or `WaspHealer` which causes the music to be overriden to `Battle3`
|
||||
- Caller is this enemy
|
||||
- With the ability to run
|
||||
|
||||
@@ -16,34 +16,34 @@ The following are all the possible `ObjectTypes` (NOT REFERENCED means the game
|
||||
|Value|Name|Summary|
|
||||
|----:|----|----------|
|
||||
|0|None|No operations or this NPCControl isn't an `Object`|
|
||||
|1|[BeetleGrass](ObjectTypes/BeetleGrass.md)|A grass that can be cut by Kabbu's Horn Slash. Can either be bound to a [crystalbfflags](../../../Enums%20and%20IDs/crystalbfflags.md) slot which will be dropped, or a list of [items](../../../Enums%20and%20IDs/Items.md) that can be dropped alongside the activation of a [flag](../../../Flags%20arrays/flags.md) and [regionalflag](../../../Flags%20arrays/Regionalflags.md) slots.|
|
||||
|1|[BeetleGrass](ObjectTypes/BeetleGrass.md)|A grass that can be cut by Kabbu's Horn Slash. Can either be bound to a [crystalbfflags](../../Enums%20and%20IDs/crystalbfflags.md) slot which will be dropped, or a list of [items](../../Enums%20and%20IDs/Items.md) that can be dropped alongside the activation of a [flag](../../Flags%20arrays/flags.md) and [regionalflag](../../Flags%20arrays/Regionalflags.md) slots.|
|
||||
|2|[PushRock](ObjectTypes/PushRock.md)|A rock or a pushable ice cube that can be moved using Kabbu's Horn Slash with configurable movement force. See the simplified explanation section for an intuitive description of how this object functions.|
|
||||
|3|[PressurePlate](ObjectTypes/PressurePlate.md)|A plate that can be pushed down in its receptacle using a [PushRock](PushRock.md) or optionally, the player or an NPCControl entity.`icecube`. This can optionally start an [event](../../../Enums%20and%20IDs/Events.md) when actuated for the first time.|
|
||||
|4|[ANDGate](ObjectTypes/ANDGate.md)|A multipurpose condition checker that can be operated in 4 distinct modes involving either [flag](../../../Flags%20arrays/flags.md) or other map entities's `hit` value which results in either a new `hit` value or an [event](../../../Enums%20and%20IDs/Events.md) being started.|
|
||||
|3|[PressurePlate](ObjectTypes/PressurePlate.md)|A plate that can be pushed down in its receptacle using a `PushRock` or optionally, the player or an NPCControl entity.`icecube`. This can optionally start an [event](../../Enums%20and%20IDs/Events.md) when actuated for the first time.|
|
||||
|4|[ANDGate](ObjectTypes/ANDGate.md)|A multipurpose condition checker that can be operated in 4 distinct modes involving either [flag](../../Flags%20arrays/flags.md) or other map entities's `hit` value which results in either a new `hit` value or an [event](../../Enums%20and%20IDs/Events.md) being started.|
|
||||
|5|[CameraChange](ObjectTypes/CameraChange.md)|A trigger zone to change the camera's properties.|
|
||||
|6|[Item](ObjectTypes/Item.md)|A collectable [item](../../../Enums%20and%20IDs/Items.md) or crystal berry bound to a [crystalbfflags](../../../Enums%20and%20IDs/crystalbfflags.md) slot whose item id is the entity.`animid` field. This extends the logic of an [item entity](../../EntityControl/Item%20entity.md).|
|
||||
|6|[Item](ObjectTypes/Item.md)|A collectable [item](../../Enums%20and%20IDs/Items.md), [medal](../../Enums%20and%20IDs/Medal.md) or crystal berry bound to a [crystalbfflags](../../Enums%20and%20IDs/crystalbfflags.md) slot whose item id is the entity.`animid` field. This extends the logic of an [item entity](../EntityControl/Item%20entity.md).|
|
||||
|7|[DoorOtherMap](ObjectTypes/DoorOtherMap.md)|A loading zone to another map with customisable movement before and after the load.|
|
||||
|8|[SetPlayerRespawn](ObjectTypes/SetPlayerRespawn.md)|A trigger zone that sets the player.`lastpos` which is the player last spawn point. It can either be managed by this NPCControl or be a completely independant collider that PlayerControl can collider with.|
|
||||
|9|[DoorSameMap](ObjectTypes/DoorSameMap.md)|A transition zone to and away from an inside of the current map.|
|
||||
|10|[Beemerang](ObjectTypes/Beemerang.md)|Vi's Beemerang when thrown. This object type is only created dynamically.|
|
||||
|11|[EventTrigger](ObjectTypes/EventTrigger.md)|An [event](../../../Enums%20and%20IDs/Events.md) trigger zone. It can either unconditionally trigger as a one shot event on the first Update cycle or trigger via OnTriggerStay that starts the event when the player collides with it with the option to destroy the NPCControl after.|
|
||||
|12|[DialogueTrigger](ObjectTypes/DialogueTrigger.md)|A zone where a [SetText](../../../SetText/SetText.md) call starts in [dialogue mode](../../../SetText/Dialogue%20mode.md) using a map dialogue line id. It can either unconditionally trigger as a one shot call on the first Update cycle or trigger via OnTriggerStay that starts the call when the player collides with it with the option to destroy the NPCControl after.|
|
||||
|13|[ANDBlock](ObjectTypes/ANDBlock.md)|A multipurpose condition checker that can be operated in 3 distinct modes involving either [flags](../../../Flags%20arrays/flags.md) or other NPCControl's `hit` value which results in a new `hit` value that can contol the entity.`sprite` local position.|
|
||||
|11|[EventTrigger](ObjectTypes/EventTrigger.md)|An [event](../../Enums%20and%20IDs/Events.md) trigger zone. It can either unconditionally trigger as a one shot event on the first Update cycle or trigger via OnTriggerStay that starts the event when the player collides with it with the option to destroy the NPCControl after.|
|
||||
|12|[DialogueTrigger](ObjectTypes/DialogueTrigger.md)|A zone where a [SetText](../../SetText/SetText.md) call starts in [dialogue mode](../../SetText/Dialogue%20mode.md) using a map dialogue line id. It can either unconditionally trigger as a one shot call on the first Update cycle or trigger via OnTriggerStay that starts the call when the player collides with it with the option to destroy the NPCControl after.|
|
||||
|13|[ANDBlock](ObjectTypes/ANDBlock.md)|A multipurpose condition checker that can be operated in 3 distinct modes involving either [flags](../../Flags%20arrays/flags.md) or other NPCControl's `hit` value which results in a new `hit` value that can contol the entity.`sprite` local position.|
|
||||
|14|[SavePoint](ObjectTypes/SavePoint.md)|A save crystal that can be hit using field abilities. It can be blue which only prompts to save the game, yellow which also heals the party and red which alerts a DeadLanderOmega, but doesn't prompt for saving and can optionally heal the party.|
|
||||
|15|[JumpSpring](ObjectTypes/JumpSpring.md)|A spring that makes an entity jump up high via [Jump](../../EntityControl/EntityControl%20Methods.md#jump) when touched or makes the entity jump straight to a specific point via [JumpTo](../../EntityControl/EntityControl%20Methods.md#JumpTo) with the option to trigger an inside transition via a [DoorSameMap](DoorSameMap.md) present on the map without physically moving the player.|
|
||||
|16|[DigSpot](ObjectTypes/DigSpot.md)|A spot where an [item](../../../Enums%20and%20IDs/Items.md), [medal](../../../Enums%20and%20IDs/Medal.md) or Crystal Berry can be dug out or have an [event](../../../Enums%20and%20IDs/Events.md) be triggered when doing so using Kabbu's Dig ability.|
|
||||
|17|[Switch](ObjectTypes/Switch.md)|A switch that can be turned on or off offering a wide variety of actuation flow such as starting an [event](../../../Enums%20and%20IDs/Events.md), changing other `hit` values, offer a toggling feature and be only actuable using Kabbu's horn. Consult the switch actuation section for more details.|
|
||||
|15|[JumpSpring](ObjectTypes/JumpSpring.md)|A spring that makes an entity jump up high via [Jump](../EntityControl/EntityControl%20Methods.md#jump) when touched or makes the entity jump straight to a specific point via [JumpTo](../EntityControl/EntityControl%20Methods.md#JumpTo) with the option to trigger an inside transition via a `DoorSameMap` present on the map without physically moving the player.|
|
||||
|16|[DigSpot](ObjectTypes/DigSpot.md)|A spot where an [item](../../Enums%20and%20IDs/Items.md), [medal](../../Enums%20and%20IDs/Medal.md) or Crystal Berry can be dug out or have an [event](../../Enums%20and%20IDs/Events.md) be triggered when doing so using Kabbu's Dig ability.|
|
||||
|17|[Switch](ObjectTypes/Switch.md)|A switch that can be turned on or off offering a wide variety of actuation flow such as starting an [event](../../Enums%20and%20IDs/Events.md), changing other `hit` values, offer a toggling feature and be only actuable using Kabbu's horn. Consult the switch actuation section for more details.|
|
||||
|18|MusicChange|NOT REFERENCED|
|
||||
|19|[CoiledObject](ObjectTypes/CoiledObject.md)|A coil that can trap another map entity within using a configurable local position and requires to be hit by a player ability to untrap the object. It can optionally set a [flag](../../../Flags%20arrays/flags.md) slot to true when hit.|
|
||||
|20|[FixedAnim](ObjectTypes/FixedAnim.md)|An object where the entity is left in a fixed [animstate](../../EntityControl/Animations/animstate.md) with the option to also disables the entity.`ccol` and gravity on it.|
|
||||
|19|[CoiledObject](ObjectTypes/CoiledObject.md)|A coil that can trap another map entity within using a configurable local position and requires to be hit by a player ability to untrap the object. It can optionally set a [flag](../../Flags%20arrays/flags.md) slot to true when hit.|
|
||||
|20|[FixedAnim](ObjectTypes/FixedAnim.md)|An object where the entity is left in a fixed [animstate](../EntityControl/Animations/animstate.md) with the option to also disables the entity.`ccol` and gravity on it.|
|
||||
|21|DigWall|NOT REFERENCED|
|
||||
|22|ItemSpawner|NOT REFERENCED|
|
||||
|23|[EnemySpawner](ObjectTypes/EnemySpawner.md)|An enemy spawner attached to another [Enemy](../NPCType.md#enemy) entity that will continuously respawn in a given circle range whenever it dies after a certain amount of time. The map entity id of the enemy, the time interval to wait before respawn and the range at which the enemy will spawn is configurable with the option to spawn the enemy immediately on the first Update cycle.|
|
||||
|23|[EnemySpawner](ObjectTypes/EnemySpawner.md)|An enemy spawner attached to another [Enemy](Enemy.md) entity that will continuously respawn in a given circle range whenever it dies after a certain amount of time. The map entity id of the enemy, the time interval to wait before respawn and the range at which the enemy will spawn is configurable with the option to spawn the enemy immediately on the first Update cycle.|
|
||||
|24|[Dropplet](ObjectTypes/Dropplet.md)|A water dropplet that can be frozen by Leif's Freeze which then turns it into an ice cube that can be moved by launching it using Kabbu's Horn Slash. The push velocity vector when launched is configurable and the object also supports many optional features, see the data array definition for details.|
|
||||
|25|[PathPlatform](ObjectTypes/PathPlatform.md)|A platform that moves on a set path defined by multiple absolute position vectors called nodes and can conditionally be stopped depending on the `hit` value of other NPCControl present on the map. Can be operated in loop mode using only 2 nodes or with multiple nodes in path mode with more options.|
|
||||
|26|[BreakableRock](ObjectTypes/BreakableRock.md)|A rock that can be broken using Kabbu's Horn Dash or shook by Kabbu's Horn Slash.|
|
||||
|27|[RotatingPlatform](ObjectTypes/RotatingPlatform.md)|The same than [PathPlatform](PathPlatform.md), but path mode will have the nodes be euler angles vectors instead and the platform will rotate through these angles instead of moving. Loop mode is left unchanged, but is considered invalid.|
|
||||
|28|[Geizer](ObjectTypes/Geizer.md)|A water or honey geizer that can be frozen using Leif's Freeze and it can elevate a [Dropplet](Dropplet.md) ice cube. The oscillation and time to stay frozen are configurable with the option to conditionally activate it when another NPCControl `hit` is true.|
|
||||
|27|[RotatingPlatform](ObjectTypes/RotatingPlatform.md)|The same than `PathPlatform`, but path mode will have the nodes be euler angles vectors instead and the platform will rotate through these angles instead of moving. Loop mode is left unchanged, but is considered invalid.|
|
||||
|28|[Geizer](ObjectTypes/Geizer.md)|A water or honey geizer that can be frozen using Leif's Freeze and it can elevate a `Dropplet` ice cube. The oscillation and time to stay frozen are configurable with the option to conditionally activate it when another NPCControl `hit` is true.|
|
||||
|29|[MusicRange](ObjectTypes/MusicRange.md)|A spherical radius that when the player enters it, changes the current music playing. The music, amount of frames to wait between distance checks, radius, rate of volume change and max volume are configurable.|
|
||||
|30|[TempPlatform](ObjectTypes/TempPlatform.md)|A platform that can only be stood on by the player for a limited amount of time before respawning the player. The amount of frames the player can stay on it and some animation timings are configurable.|
|
||||
|31|[ScrewSwitch](ObjectTypes/ScrewSwitch.md)|A crank switch actuated by Vi's Beemerang Toss with an analog actuation that needs to be held for a certain period before being fully actuated. The angles of rotation when actuated, the rate of actuation / deactuation and the maximum value to reach before fully actuating the crank are all configurable.|
|
||||
|
||||
@@ -5,13 +5,14 @@ A multipurpose condition checker that can be operated in 3 distinct modes involv
|
||||
- `data`: Control the mode of operations and data to check. See the table below for details.
|
||||
- `vectordata[0]`: The local position to set the entity.`sprite` when `hit` goes to true.
|
||||
- `vectordata[1].x`: The factor of the lerp to use after setting this object's `hit` during Update
|
||||
- `vectordata[2]`: The entity.`startscale` and the local scale of the entity.`sprite`. This is optional, neither are changed if the magnitude is \<= 0.1 or does not exist.
|
||||
- `vectordata[2]`: The entity.`startscale` and the local scale of the entity.`sprite`. This is optional, neither are changed if the magnitude is <= 0.1 or does not exist.
|
||||
|
||||
## Additional data
|
||||
- `activationflag`: When configured as such, the `hit` value is set to the value of this [flag](../../../Flags%20arrays/flags.md) slot. See the table below for details.
|
||||
|
||||
## Setup
|
||||
A few adjustements occurs:
|
||||
|
||||
- The entity.`alwaysactive` is set to true
|
||||
- The gameObject's isStatic is set to true
|
||||
- The entity.`rigid` is placed in kinematic mode without gravity
|
||||
@@ -29,6 +30,7 @@ If the entity.`originalid` is the `PrisonGate` or the `PrisonGateLocal`'s [AnimI
|
||||
|
||||
## Update
|
||||
This is where the logic depending on the mode of operation occurs. There are 3 modes in which this object can operate in and it decides a new value for `hit`:
|
||||
|
||||
1. Set `hit` based on the `activationflag` [flag](../../../Flags%20arrays/flags.md) slot
|
||||
2. Set `hit` to `true` if other [flags](../../../Flags%20arrays/flags.md) slots have a desired value (set to false otherwise)
|
||||
3. Set `hit` to `true` if other `hit` value of other NPCControl have a desired value (set to false otherwise)
|
||||
@@ -36,6 +38,7 @@ This is where the logic depending on the mode of operation occurs. There are 3 m
|
||||
When checking a data value, it is possible to invert its checked value by sepcifying its negative version, but this means the value 0 cannot be checked for its inverted version. This means for example that if the value is a [flag](../../../Flags%20arrays/flags.md) slot, it will check that it is false instead of checking for being true, but it is not possible to do this for flag slot 0.
|
||||
|
||||
Consult the following table for clarity on each mode (one must apply and it will be the first where the required condition is fufilled):
|
||||
|
||||
|Mode|Condition|Value(s) checked|Result|
|
||||
|----:|--------------------|------------|------|
|
||||
|1|`data[1]` is -1 and it is the last element|`activationflag`|`hit` is set to the [flag](../../../Flags%20arrays/flags.md) slot of the value.|
|
||||
|
||||
@@ -9,6 +9,7 @@ A multipurpose condition checker that can be operated in 4 distinct modes involv
|
||||
|
||||
## Setup
|
||||
A few adjustements occurs:
|
||||
|
||||
- The entity.`alwaysactive` is set to true
|
||||
- The gameObject's isStatic is set to true
|
||||
- The entity.`rigid` is placed in kinematic mode without gravity
|
||||
@@ -18,6 +19,7 @@ A few adjustements occurs:
|
||||
|
||||
## Update
|
||||
This is where the logic depending on the mode of operation occurs. There are 4 modes in which this object can operate in:
|
||||
|
||||
1. Set `hit` based on the `activationflag` [flag](../../../Flags%20arrays/flags.md) slot
|
||||
2. Set `hit` to `true` if other [flags](../../../Flags%20arrays/flags.md) slots have a desired value (set to false otherwise)
|
||||
3. Set `hit` to `true` if other `hit` value of other NPCControl have a desired value (set to false otherwise)
|
||||
@@ -26,6 +28,7 @@ This is where the logic depending on the mode of operation occurs. There are 4 m
|
||||
When checking a data value, it is possible to invert its checked value by sepcifying its negative version, but this means the value 0 cannot be checked for its inverted version. This means for example that if the value is a [flag](../../../Flags%20arrays/flags.md) slot, it will check that it is false instead of checking for being true, but it is not possible to do this for flag slot 0.
|
||||
|
||||
Consult the following table for clarity on each mode (one must apply and it will be the first where the required condition is fufilled):
|
||||
|
||||
|Mode|Condition|Value(s) checked|Result|
|
||||
|----:|--------------------|------------|------|
|
||||
|1|`data[1]` is -1 and it is the last element|`activationflag`|`hit` is set to the [flag](../../../Flags%20arrays/flags.md) slot of the value.|
|
||||
|
||||
@@ -8,6 +8,7 @@ A zone that causes a change of the map.`battlemap`.
|
||||
|
||||
## Setup
|
||||
A few adjustements occurs:
|
||||
|
||||
- The entity.`alwaysactive` is set to true
|
||||
- The gameObject's isStatic is set to true
|
||||
- The entity.`rigid` is placed in kinematic mode without gravity
|
||||
|
||||
@@ -31,12 +31,14 @@ The `hit` value tracks on which half of the path the beemerang is on. If it's fa
|
||||
If the distance between this object and `vectordata[0]` is higher than 0.2, this object's position is set to a lerp from the existing one to `vectordata[0]` with a factor of the game's frametime * the entity's `speed`. This basically moves the beemerang to its destination.
|
||||
|
||||
Otherwise (meaning the Beemerang reached its destination), if the ability key is held, [flag](../../../Flags%20arrays/flags.md) 21 is true (got Beemerang Halt), `heldonce` is false and `WackaWorm.disablehold` is false:
|
||||
|
||||
- The entity.`sound` pitch is set to 1.25
|
||||
- The entity.`spin` is set to (0.0, 0.0, 30.0)
|
||||
- `timer` is set to 99.0 (which gives it access to a new destination on the first Update cycle when the ability button is released)
|
||||
- If `particles` is null, it's initialised to an instance of `Prefabs/Particles/ContinuousSmokeCloud` childed to this object at this object's position + Vector3.up * 0.2 with angles (-90.0, 0.0, 0.0)
|
||||
|
||||
Otherwise, if the `timer` is exactly 99.0 (meaning we were using Beemerang Halt, but released the ability input):
|
||||
|
||||
- `particles` is put offscreen at (0.0, -9999.0, 0.0) then destroyed in one second and set to null
|
||||
- The entity.`sound` pitch is set to 1.25
|
||||
- `heldonce` is set to true
|
||||
@@ -52,12 +54,14 @@ If the `timer` is higher than -2.0, it is decremented by framestep.
|
||||
If the distance between this object position and the player is higher than 0.45 the following section occurs (otherwise, this object is destroyed because it means the Beemerang completed its full travel).
|
||||
|
||||
If the `timer` is less than -2.0 (meaning the Beemerang collided with a wall), the ability key is held, [flag](../../../Flags%20arrays/flags.md) 21 is true (got Beemerang Halt), `heldonce` is false and `WackaWorm.disablehold` is false, the following happens (this whole logic allows the beemerang to stall in place even if its path got cut short by a collider):
|
||||
|
||||
- The entity.`sound` pitch is set to 1.25
|
||||
- The entity.`spin` is set to (0.0, 0.0, 30.0)
|
||||
- `timer` is set to -50.0
|
||||
- If `particles` is null, it's initialised to an instance of `Prefabs/Particles/ContinuousSmokeCloud` childed to this object at this object's position + Vector3.up * 0.2 with angles (-90.0, 0.0, 0.0)
|
||||
|
||||
Otherwise, if the ability key isn't held or the `timer` is exactly -50.0 (meaning the beemerang is ready to go back to the player):
|
||||
|
||||
- `particles` is put offscreen at (0.0, -9999.0, 0.0) then destroyed in one second and set to null
|
||||
- `heldonce` is set to true
|
||||
- `timer` is set to -100.0
|
||||
|
||||
@@ -3,13 +3,13 @@ A grass that can be cut by Kabbu's Horn Slash. Can either be bound to a [crystal
|
||||
|
||||
## Data Arrays
|
||||
- `data[0]`: The id of the grass sprite to use (NOTE: any other value than the ones below when `data[1]` doesn't apply will cause an exception to be thrown):
|
||||
- 0: a standard green grass
|
||||
- 1: a branch looking grass
|
||||
- 2: an orange grass
|
||||
- 3: a brown grass
|
||||
- 4: a dense dark green grass
|
||||
- 5: a purple grass
|
||||
- 6: a beige and gray grass
|
||||
- 0: a standard green grass
|
||||
- 1: a branch looking grass
|
||||
- 2: an orange grass
|
||||
- 3: a brown grass
|
||||
- 4: a dense dark green grass
|
||||
- 5: a purple grass
|
||||
- 6: a beige and gray grass
|
||||
- `data[1]`: If it's not negative, the [crystalbfflags](../../../Enums%20and%20IDs/crystalbfflags.md) id that will be dropped when the bush is cut. This is optional: no Crystal Berry is dropped if it doesn't exist
|
||||
- `vectordata`: The list of [items](../../../Enums%20and%20IDs/Items.md) ids (in the x component after flooring) to potentially drop. Only applicable if `data[1]` doesn't apply
|
||||
|
||||
@@ -19,10 +19,11 @@ A grass that can be cut by Kabbu's Horn Slash. Can either be bound to a [crystal
|
||||
- `activationflag`: The [flag](../../../Flags%20arrays/flags.md) slot turned to true when the bush is cut while `data[1]` isn't present or is negative (if an item is dropped, it's attached to the item created).
|
||||
|
||||
## HasHiddenItem conditions
|
||||
If `data[1]` is present and not negative, the [crystalbflags](../../Enums%20and%20IDs/crystalbfflags.md) whose id is that value must not have been obtained yet.
|
||||
If `data[1]` is present and not negative, the [crystalbflags](../../../Enums%20and%20IDs/crystalbfflags.md) whose id is that value must not have been obtained yet.
|
||||
|
||||
## Setup
|
||||
A few adjustements occurs:
|
||||
|
||||
- The entity.`alwaysactive` is set to true
|
||||
- The gameObject's isStatic is set to true
|
||||
- The entity.`rigid` is placed in kinematic mode without gravity
|
||||
@@ -33,6 +34,7 @@ A few adjustements occurs:
|
||||
If `data[1]` is present and not negative and the crystal berry corresponding to its id has been obtained, the entity.`iskill` is set to true which ends this object setup as the grass will not appear.
|
||||
|
||||
Otherwise:
|
||||
|
||||
- The layer is set to 8 (Ground)
|
||||
- The `boxcol`'s material is set to the defaultpmat.
|
||||
- The entity.`rotater` tag is set to `Hornable` which allows PlayerControl to get a green ! emoticon when getting 2.5 or lower distance from the grass for 5 frames
|
||||
@@ -40,9 +42,9 @@ Otherwise:
|
||||
- entity.`overrideanim` is set to true
|
||||
- entity.`sprite` is enabled and set to the corresponding sprite from grasssprite mentioned above and its shadowCastingMode is set to TwoSided
|
||||
- Unless nowindeffect is true (meaning Wind Effects in the settings is Off), the entity.`sprite` material is set to the windShader and RefreshWind is called on the entity.`sprite` which sets the shader property to be:
|
||||
- `_ShakeDisplacement`: random betweent half the map.`windspeed` and it's actual value
|
||||
- `_ShakeBending`: random betweent half the map.`windintensity` and it's actual value
|
||||
- `_ShakeTime`: random betweent 0.075 and 0.25
|
||||
- `_ShakeDisplacement`: random betweent half the map.`windspeed` and it's actual value
|
||||
- `_ShakeBending`: random betweent half the map.`windintensity` and it's actual value
|
||||
- `_ShakeTime`: random betweent 0.075 and 0.25
|
||||
|
||||
## Update
|
||||
If the `timer` hasn't expired yet, it is decremented by the game's frametime clamped from 0.0 to infinity. Otherwise, if it is 0.0 and the entity isn't `dead`, a [Death](../../EntityControl/Notable%20methods/Death.md) coroutine is started with the entity.
|
||||
@@ -52,6 +54,7 @@ If the other gameObject tag is `BeetleHorn` or `BeetleDash` while `hit` is false
|
||||
|
||||
### CutGrass
|
||||
A number of steps occurs:
|
||||
|
||||
- The `rustling1` is played on entity
|
||||
- The entity.`rotater` tag is set to `Object` (this removes its Hornable property).
|
||||
- `hit` gets set to true (which prevents OnTriggerEnter to act again)
|
||||
@@ -62,6 +65,7 @@ From there, this is where the potential item drop and flag slots edits occurs.
|
||||
|
||||
#### Crystal Berry drop
|
||||
If `data[1]` is present and not negative, [CreateItem](Item.md#entitycontrolcreateitem) is called with the following:
|
||||
|
||||
- starpos of this transform + (0.0, 0.5, 0.0)
|
||||
- itemtype of 3 (Crystal Berry)
|
||||
- itemid of `data[1]`
|
||||
@@ -70,6 +74,7 @@ If `data[1]` is present and not negative, [CreateItem](Item.md#entitycontrolcrea
|
||||
|
||||
#### Potential Item Drop
|
||||
If `data[1]` isn't present or is negative, `vectordata` is checked to see if we are going to drop an item. The way this is done is selecting a uniform random valid index of a `vectordata` element. It is valid if it's not negative. If it is valid, [CreateItem](Item.md#entitycontrolcreateitem) is called which creates an [Item](Item.md) object with the following:
|
||||
|
||||
- starpos of this transform + (0.0, 0.5, 0.0)
|
||||
- itemtype of 0 (Standard item)
|
||||
- itemid of `vectordata[i].x` floored where `i` is the random index generated earlier
|
||||
@@ -81,6 +86,7 @@ Once the creation is done, the `regionalflag` and `activationflag` of the new it
|
||||
In the case where `vectordata` is empty or the generated index leads to a negative value of the element x component, the logic is limited to set the flag and regionalflag slots of this object's `regionalflag` and `activationflag` to true.
|
||||
|
||||
No matter which cases we land into, there is always a 13% chance to call [CreateItem](Item.md#entitycontrolcreateitem) a second time with the following:
|
||||
|
||||
- starpos of this transform + (0.0, 0.5, 0.0)
|
||||
- itemtype of 0 (Standard item)
|
||||
- itemid of 6 (`MoneySmall`)
|
||||
@@ -91,6 +97,7 @@ No matter which cases we land into, there is always a 13% chance to call [Create
|
||||
For any cases at the end of the method, if we dropped any item or Crystal Berry, all collisions between the item and this object's entity are ignored.
|
||||
|
||||
Finally, a GrassFade coroutine is started. The purpose of that coroutine is only for rendering the cut part of the grass which is done by creating a new gameObject named `grass` with a SpriteRenderer, SphereCollider, BoxCollider and RigidBody where the sprite is the cut grass version according to `data[0]`. For brevety, the full details of this effect won't be detailed, but a couple of things is worth to mention:
|
||||
|
||||
- The grass layer is set to 9 (Follower)
|
||||
- A torque is applied on the grass of RandomItemBounce(5.0, 0.0)
|
||||
- The starting velocity is (0.0, 10.0, 0.0)
|
||||
|
||||
@@ -3,12 +3,12 @@ A rock that can be broken using Kabbu's Horn Dash or shook by Kabbu's Horn Slash
|
||||
|
||||
## Data Arrays
|
||||
- `data[0]`: The color of the rock material selectable among 6 different ones:
|
||||
- 0: FFFFFF (pure white)
|
||||
- 1: ED9121 (mostly orange)
|
||||
- 2: EDD872 (light yellow)
|
||||
- 3: BCD1ED (light gray)
|
||||
- 4: 84BF6B (light green)
|
||||
- 5: A03F70 (light magenta)
|
||||
- 0: FFFFFF (pure white)
|
||||
- 1: ED9121 (mostly orange)
|
||||
- 2: EDD872 (light yellow)
|
||||
- 3: BCD1ED (light gray)
|
||||
- 4: 84BF6B (light green)
|
||||
- 5: A03F70 (light magenta)
|
||||
|
||||
## Additional data
|
||||
- `boxcol`: Required to be present with valid data, but the center and size are overriden to (0.0, 2.5, 0.0) and (5.0, 5.0, 5.0) respectively
|
||||
@@ -17,6 +17,7 @@ A rock that can be broken using Kabbu's Horn Dash or shook by Kabbu's Horn Slash
|
||||
|
||||
## Setup
|
||||
A few adjustements occurs:
|
||||
|
||||
- The entity.`alwaysactive` is set to true
|
||||
- The gameObject's isStatic is set to true
|
||||
- The entity.`rigid` is placed in kinematic mode without gravity
|
||||
@@ -25,6 +26,7 @@ A few adjustements occurs:
|
||||
- The `scol` is disabled
|
||||
|
||||
[AddModel](../../EntityControl/Notable%20methods/AddModel.md) is called on the entity with the path `Prefabs/Objects/CrackedRock` with offset (-1.0, 0.0, 1.5). The material's color depends on `data[0]` (any other value has it unchanged):
|
||||
|
||||
- 0: FFFFFF (pure white)
|
||||
- 1: ED9121 (mostly orange)
|
||||
- 2: EDD872 (light yellow)
|
||||
@@ -35,10 +37,11 @@ A few adjustements occurs:
|
||||
The tag of this object is set to `DroppletPass` with a layer of 13 (NoDigGround) This was supposed to allow a [Dropplet](Dropplet.md) to pass through the rock instead of colliding with it, but the tag is overriden to `Object` later making this not work.
|
||||
|
||||
The following occurs:
|
||||
|
||||
- entity.`rotater` tag is set to `Hornable` which allows PlayerControl to get a green ! emoticon when getting 2.5 or lower distance from the grass for 5 frames
|
||||
- entity.`rigid` has all its constaints frozen
|
||||
- `boxcol`.center is overriden to (0.0, 2.5, 0.0) and the size is overriden to Vector3.one * 5.0
|
||||
- [AddPusher](../AddPusher.md) is called and the height of the `pusher` is overriden to 0.0 and the radius to 3.5. The local position of the `pusher` is set to (0.0, 3.0, 0.0).
|
||||
- [AddPusher](../Notable%20methods/AddPusher.md) is called and the height of the `pusher` is overriden to 0.0 and the radius to 3.5. The local position of the `pusher` is set to (0.0, 3.0, 0.0).
|
||||
|
||||
## Update
|
||||
If the `timer` hasn't expired yet, it is decremented by the game's frametime clamped from 0.0 to infinity. Otherwise, if it is 0.0 and the entity isn't `dead`, a [Death](../../EntityControl/Notable%20methods/Death.md) coroutine is started with the entity.
|
||||
@@ -64,6 +67,7 @@ This is a public method that has logic specific to this object type.
|
||||
If the player is less than 15.0 away from this object and the `RockBreak` sound wasn't playing, it is played at 0.5 volume.
|
||||
|
||||
Nothing happens if `hit` is true (prevents to call this when the rock is already broken). If it's false:
|
||||
|
||||
- A `Prefabs/Objects/CrackRockBreak` prefab is instantiated at the rock's position and its CrackedRockBreak's initialcolore is set to the rock's material color
|
||||
- `regionalflag` and `activationflag` flags array slots are set to true when applicable
|
||||
- `hit` is set to true
|
||||
|
||||
@@ -20,6 +20,7 @@ A trigger zone to change the camera's properties.
|
||||
|
||||
## Setup
|
||||
A few adjustements occurs:
|
||||
|
||||
- The entity.`alwaysactive` is set to true
|
||||
- The gameObject's isStatic is set to true
|
||||
- The entity.`rigid` is placed in kinematic mode without gravity
|
||||
@@ -32,6 +33,7 @@ If the `timer` hasn't expired yet, it is decremented by the game's frametime cla
|
||||
|
||||
## OnTriggerStay
|
||||
This does nothing if any of the following is true:
|
||||
|
||||
- The other gameObject isn't the player
|
||||
- The player isn't free (ignoring flying) and its entity is not `digging`
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ A coil that can trap another map entity within using a configurable local positi
|
||||
|
||||
## Setup
|
||||
A few adjustements occurs:
|
||||
|
||||
- entity.`alwaysactive` is set to true
|
||||
- gameObject's isStatic is set to true
|
||||
- entity.`rigid` is placed in kinematic mode without gravity
|
||||
@@ -37,14 +38,15 @@ NOTE: it is unknown why the game seems to specifically care about a NaN positive
|
||||
|
||||
## LateUpdate (Not a `dummy` and the entity is `incamera`)
|
||||
- If `moveobj` isn't initialised yet, `hit` is false and the entity isn't `iskill`, then `moveobj` is initialised to the NPCControl at `data[0]` as `mapid` with some adjustements:
|
||||
- Its `trapped` is set to true
|
||||
- Its entity.`rigid` is locked via [LockRigid(true)](../EntityControl/EntityControl%20Methods.md#lockrigid)
|
||||
- It gets childed to this entity.`sprite`
|
||||
- Its scale is set to Vector3.one
|
||||
- Its local position is set to `vectordata[0]`
|
||||
- Its `trapped` is set to true
|
||||
- Its entity.`rigid` is locked via [LockRigid(true)](../../EntityControl/EntityControl%20Methods.md#lockrigid)
|
||||
- It gets childed to this entity.`sprite`
|
||||
- Its scale is set to Vector3.one
|
||||
- Its local position is set to `vectordata[0]`
|
||||
|
||||
## OnTriggerEnter
|
||||
Nothing happens if all of the following are true:
|
||||
|
||||
- We are in a `pause` or `minipause`
|
||||
- [message](../../../SetText/Notable%20states.md#message) is grabbed
|
||||
- The other gameObject tag isn't `BeetleHorn`, `BeetleDash` and `Icecle` while it's not the player `beemerang`
|
||||
@@ -54,6 +56,7 @@ Nothing happens if all of the following are true:
|
||||
The `Coiled` sound is played on this entity and HitPart particles are played at this position + (0.0, 0.5, 0.0).
|
||||
|
||||
The following occurs on the entity of the `moveobj` (the trapped object):
|
||||
|
||||
- The `rigid` is unlocked via [LockRigid(false)](../../EntityControl/EntityControl%20Methods.md#lockrigid), but its velocity gets zeroed out
|
||||
- The `npcdata.trapped` is set to false
|
||||
- The `onground` is set to false
|
||||
@@ -70,8 +73,9 @@ Finally, `hit` is set to true.
|
||||
|
||||
## Effects of being `trapped`
|
||||
This field is specific to this object and the object being `trapped` receives some specific effects:
|
||||
|
||||
- If it's a [PushRock](PushRock.md), OnTriggerEnter becomes disabled preventing the rock to be moved by Kabbu's Horn Slash
|
||||
- [CheckItem](../Notable%20methods/CheckItem.md) prevents any `trapped` [Item](Item.md) from being obtained by the player.
|
||||
- [CheckItem](Item.md#checkitem) prevents any `trapped` [Item](Item.md) from being obtained by the player.
|
||||
- It won't receive active NPCControl updates unless entity.`activeonpause` is true (and even if it is, it can only receive updates if it's an [Enemy](../NPCType.md#enemy) with one of the 3 active update override cases)
|
||||
- Any inactive updates will skip setting the position to entity.`startpos`
|
||||
- The entity's [UpdateVelocity](../../EntityControl/Update%20process/UpdateVelocity.md) effects are only active every 2 frames when the npcdata.`entitytype` isn't [NPC](../NPC.md)
|
||||
|
||||
@@ -12,6 +12,7 @@ A zone where a [SetText](../../../SetText/SetText.md) call starts in [dialogue m
|
||||
|
||||
## Setup
|
||||
A few adjustements occurs:
|
||||
|
||||
- The entity.`alwaysactive` is set to true
|
||||
- The gameObject's isStatic is set to true
|
||||
- The entity.`rigid` is placed in kinematic mode without gravity
|
||||
@@ -23,14 +24,15 @@ A few adjustements occurs:
|
||||
Updates are disabled if `data[2]` doesn't exist or isn't -1 or we are in `pause`, `minipause` or `inevent`. All Update does is manage the unconditional one shot trigger feature.
|
||||
|
||||
If the above is fufilled:
|
||||
|
||||
- CancelAction is called on the player
|
||||
- [SetText](../../../SetText/SetText.md) is called in [dialogue mode](../../../SetText/Dialogue%20mode.md) using the map dialogue line id `data[0]`:
|
||||
- [fonttype](../../../SetText/Notable%20states.md#fonttype) of 0 (`BubblegumSans`)
|
||||
- Standard messagebreak as `linebreak`
|
||||
- No `tridimensional`
|
||||
- No local `position` change, no `camoffset` change or `size` change
|
||||
- This transform as the `parent`
|
||||
- No `caller`
|
||||
- [fonttype](../../../SetText/Notable%20states.md#fonttype) of 0 (`BubblegumSans`)
|
||||
- Standard messagebreak as `linebreak`
|
||||
- No `tridimensional`
|
||||
- No local `position` change, no `camoffset` change or `size` change
|
||||
- This transform as the `parent`
|
||||
- No `caller`
|
||||
|
||||
If the current map supports the [global commands](../../../SetText/Related%20Systems/GlobalCommand.md) system, the map's `currentline` is set to `data[0]`.
|
||||
|
||||
@@ -38,6 +40,7 @@ Finally, this object gets destroyed.
|
||||
|
||||
## OnTriggerStay
|
||||
This does nothing if any of the following is true:
|
||||
|
||||
- The other gameObject isn't the player
|
||||
- We are `inevent`
|
||||
- We are in a `pause`
|
||||
@@ -46,6 +49,7 @@ This does nothing if any of the following is true:
|
||||
The [regionalflag](../../../Flags%20arrays/Regionalflags.md) slot at `regionalflags` and the [flag](../../../Flags%20arrays/flags.md) slot at `activationflag` are set to true.
|
||||
|
||||
If we aren't in a `minipause`, a WaitForEvent coroutine starts which does the following:
|
||||
|
||||
- `hit` is set to true (this prevents a second trigger)
|
||||
- We enter a `minipause`
|
||||
- Yield frames until `switchcooldown` expires
|
||||
@@ -53,12 +57,12 @@ If we aren't in a `minipause`, a WaitForEvent coroutine starts which does the fo
|
||||
- Call CancelAction on the player
|
||||
- Yield a frame
|
||||
- Calls [SetText](../../../SetText/SetText.md) in [dialogue mode](../../../SetText/Dialogue%20mode.md) with the input string being the one resolved by the [dialogue line id](../../../SetText/Common%20commands%20id%20schemes/Dialogue%20line%20id.md) contained in `data[0]`:
|
||||
- `BubblegumSans` as the [fonttype](../../../SetText/Notable%20states.md#fonttype)
|
||||
- The default `messagebreak` as the linebreak
|
||||
- No tridimensional
|
||||
- No position and camera offsets
|
||||
- Size of Vector3.one
|
||||
- This as the parent
|
||||
- No caller
|
||||
- `BubblegumSans` as the [fonttype](../../../SetText/Notable%20states.md#fonttype)
|
||||
- The default `messagebreak` as the linebreak
|
||||
- No tridimensional
|
||||
- No position and camera offsets
|
||||
- Size of Vector3.one
|
||||
- This as the parent
|
||||
- No caller
|
||||
- `hit` is set to false
|
||||
- If `data[1]` isn't 0 or doesn't exist, the object is destroyed
|
||||
|
||||
@@ -3,13 +3,13 @@ A spot where an [item](../../../Enums%20and%20IDs/Items.md), [medal](../../../En
|
||||
|
||||
## Data Arrays
|
||||
- `data[0]`: This has 3 possible meanings:
|
||||
- If it's 1, it indicates that there is a crystal berry hidden in this spot
|
||||
- If it's 2 or above, it indicates that an [event](../../../Enums%20and%20IDs/Events.md) will start when the dig spot is dug up
|
||||
- If it's 0 or less, it indicates that there is an [item](../../../Enums%20and%20IDs/Items.md) or [medal](../../../Enums%20and%20IDs/Medal.md) hidden in this spot
|
||||
- If it's 1, it indicates that there is a crystal berry hidden in this spot
|
||||
- If it's 2 or above, it indicates that an [event](../../../Enums%20and%20IDs/Events.md) will start when the dig spot is dug up
|
||||
- If it's 0 or less, it indicates that there is an [item](../../../Enums%20and%20IDs/Items.md) or [medal](../../../Enums%20and%20IDs/Medal.md) hidden in this spot
|
||||
- `data[1]`: The meaning depends on `data[0]`:
|
||||
- If `data[0]` is 2 or above, the [event](../../../Enums%20and%20IDs/Events.md) id that will start when the dig spot is dug up
|
||||
- If `data[0]` is 1, the [crystalbfflags](../../../Enums%20and%20IDs/crystalbfflags.md) slot hidden in this spot
|
||||
- If `data[0]` is 0 or less, the item type hidden in this spot
|
||||
- If `data[0]` is 2 or above, the [event](../../../Enums%20and%20IDs/Events.md) id that will start when the dig spot is dug up
|
||||
- If `data[0]` is 1, the [crystalbfflags](../../../Enums%20and%20IDs/crystalbfflags.md) slot hidden in this spot
|
||||
- If `data[0]` is 0 or less, the item type hidden in this spot
|
||||
- `data[2]`: If `data[0]` is 0 or less, the [item](../../../Enums%20and%20IDs/Items.md) or [medal](../../../Enums%20and%20IDs/Medal.md) id hidden inside this spot. This can be considered mandatory if `data[0]` isn't 1 because it is still expected to be present even if `data[0]` is 2 which doesn't make use of this field. It is optional if `data[0]` is 1 as the value is ignored
|
||||
|
||||
## Additional data
|
||||
@@ -19,12 +19,13 @@ A spot where an [item](../../../Enums%20and%20IDs/Items.md), [medal](../../../En
|
||||
## HasHiddenItem conditions
|
||||
The condition depends on `data[0]`.
|
||||
|
||||
If `data[0]` is 1, the [crystalbflags](../../Enums%20and%20IDs/crystalbfflags.md) whose id is `data[1]` must not have been obtained yet.
|
||||
If `data[0]` is 1, the [crystalbflags](../../../Enums%20and%20IDs/crystalbfflags.md) whose id is `data[1]` must not have been obtained yet.
|
||||
|
||||
If `data[0]` isn't 1, then `data[1]` must be 1 (key item) and `data[2]` must be 52 (Lore Book).
|
||||
|
||||
## Setup
|
||||
A few adjustements occurs:
|
||||
|
||||
- The entity.`alwaysactive` is set to true
|
||||
- The gameObject's isStatic is set to true
|
||||
- The entity.`rigid` is placed in kinematic mode without gravity
|
||||
@@ -39,6 +40,7 @@ If the `timer` hasn't expired yet, it is decremented by the game's frametime cla
|
||||
|
||||
## OnTriggerStay
|
||||
This does nothing if any of the following are true:
|
||||
|
||||
- The entity.`iskill` is true
|
||||
- The other gameObject isn't the player
|
||||
- The player `uproot` is false (meaning the player wasn't preparing to go back to the surface after stopping to dig)
|
||||
@@ -46,6 +48,7 @@ This does nothing if any of the following are true:
|
||||
The `DigPop2` sound is played following by `DigPop`, but with 0.7 volume.
|
||||
|
||||
If `data[0]` is 2 or above, a WaitForEvent coroutine starts which does the following:
|
||||
|
||||
- `hit` is set to true
|
||||
- We enter a `minipause`
|
||||
- Yield frames until `switchcooldown` expires
|
||||
@@ -56,12 +59,13 @@ If `data[0]` is 2 or above, a WaitForEvent coroutine starts which does the follo
|
||||
- `hit` is set to false
|
||||
|
||||
Otherwise (meaning there is an item or a Crystal Berry hidden in this spot):
|
||||
|
||||
- [CreateItem](Item.md#entitycontrolcreateitem) is called with:
|
||||
- This object's position as the startpos,
|
||||
- If `data[0]` is 1, 3 (Crystal Berry) is the itemtype, it's `data[1]` otherwise
|
||||
- If `data[0]` is 1, `data[1]` is the itemid (which is a [crystalbfflags](../../../Enums%20and%20IDs/crystalbfflags.md) slot), it's `data[2]` otherwise
|
||||
- RandomItemBounce(4.0, 15.0) as the direction
|
||||
- If `data[0]` is 0 or less (there is an item or medal hidden in this spot), the timer is 300.0 if `data[1]` is 0 (standard item). It is -1 (no timer) otherwise
|
||||
- This object's position as the startpos,
|
||||
- If `data[0]` is 1, 3 (Crystal Berry) is the itemtype, it's `data[1]` otherwise
|
||||
- If `data[0]` is 1, `data[1]` is the itemid (which is a [crystalbfflags](../../../Enums%20and%20IDs/crystalbfflags.md) slot), it's `data[2]` otherwise
|
||||
- RandomItemBounce(4.0, 15.0) as the direction
|
||||
- If `data[0]` is 0 or less (there is an item or medal hidden in this spot), the timer is 300.0 if `data[1]` is 0 (standard item). It is -1 (no timer) otherwise
|
||||
- If `data[0]` is 0 or less, the `activationflag` and `regionalflag` of the created item are set to the corresponding ones from this object
|
||||
- All collisions between the entity and the created item's entity are ignored
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ The `insideid` is set to -2 which excludes it from the MapControl.RefreshInsides
|
||||
|
||||
## Setup
|
||||
A few adjustements occurs:
|
||||
|
||||
- The entity.`alwaysactive` is set to true
|
||||
- The gameObject's isStatic is set to true
|
||||
- The entity.`rigid` is placed in kinematic mode without gravity
|
||||
@@ -45,6 +46,7 @@ After 20 frames has passed since the load of the map and every 2 frames, this ob
|
||||
|
||||
## OnTriggerStay
|
||||
This does nothing if any of the following is true:
|
||||
|
||||
- The other gameObject isn't the player
|
||||
- We are `inevent`
|
||||
- We are in a `pause`
|
||||
|
||||
@@ -24,6 +24,7 @@ This is also where if `data[1]` exists with a [music](../../../Enums%20and%20IDs
|
||||
|
||||
## Setup
|
||||
A few adjustements occurs:
|
||||
|
||||
- The entity.`alwaysactive` is set to true
|
||||
- The gameObject's isStatic is set to true
|
||||
- The entity.`rigid` is placed in kinematic mode without gravity
|
||||
@@ -41,6 +42,7 @@ This object type is excluded from this logic meaning it will never get deactivat
|
||||
|
||||
## OnTriggerStay
|
||||
This does nothing if any of the following is true:
|
||||
|
||||
- The other gameObject isn't the player
|
||||
- We are `inevent`
|
||||
- We are in a `pause`
|
||||
|
||||
@@ -5,9 +5,9 @@ A water dropplet that can be frozen by Leif's Freeze which then turns it into an
|
||||
- `data[0]`: The time interval in frames between main Updates where the ice cube and dropplet are managed. This allows to throttle those updates
|
||||
- `data[1]`: If above 0, the max distance in units the cube can away of entity.`startpos` + `vectordata[0]`. If the ice cube goes further, it will be shattered via ShatterDroppletIce. This isn't enforced if the value is 0 or below
|
||||
- `data[2]`: There are 3 possible meanings:
|
||||
- If 0, entity.`shadow` is always kept enabled and when the dropplet is frozen, its position is set to be offscreen immediately
|
||||
- If 1, entity.`shadow` is only enabled when `hit` is false (no ice cube exists) and when the dropplet is frozen, the entity.`rigid` is put in kinematic mode and the dropplet position is set to be offscreen in 0.1 seconds. This also allows `data[3]` to take effect if applicable
|
||||
- Any other value: If 1, entity.`shadow` is only enabled when `hit` is false (no ice cube exists) and when the dropplet is frozen, its position is set to be offscreen immediately
|
||||
- If 0, entity.`shadow` is always kept enabled and when the dropplet is frozen, its position is set to be offscreen immediately
|
||||
- If 1, entity.`shadow` is only enabled when `hit` is false (no ice cube exists) and when the dropplet is frozen, the entity.`rigid` is put in kinematic mode and the dropplet position is set to be offscreen in 0.1 seconds. This also allows `data[3]` to take effect if applicable
|
||||
- Any other value: If 1, entity.`shadow` is only enabled when `hit` is false (no ice cube exists) and when the dropplet is frozen, its position is set to be offscreen immediately
|
||||
- `data[3]`: If `data[2]` is 1 and this value is above 0, the time period in frames that the ice cube is allowed to exist before shattering via ShatterDroppletIce on its own. This is optional, this feature is disabled if it doesn't exist or is 0 or below. NOTE: specifying a value above 0 while `data[2]` isn't 1 is considered invalid and will cause the ice cube to shatter on the first throttled update
|
||||
- `data[4]`: If 1, the ice cube can only be launched in the 8 cardinal directions relative to the camera instead of having free movement in x and z
|
||||
- `vectordata[0]`: If `data[1]` is above 0, this is an offset position where its value + `startpos` is the center of the range where the ice cube is allowed to stay with a max distance of `data[1]`. If the ice cube goes out of this range, it is shattered via ShatterDroppletIce
|
||||
@@ -24,6 +24,7 @@ A water dropplet that can be frozen by Leif's Freeze which then turns it into an
|
||||
- entity.`shadow` is ensured to be created if it wasn't
|
||||
|
||||
From there, `internaltransform` is initialised to one element which is an instance of the `Prefabs/Objects/icecube` prefab which is then childed to the map. Some adjustements are performed on it:
|
||||
|
||||
- The layer is set to 13 (NoDigGround)
|
||||
- The local scale is set to Vector3.one * 1.5
|
||||
- A RigidBody is added on it with kinematic and rotation frozen with a mass of 100000.0
|
||||
@@ -34,6 +35,7 @@ From there, `internaltransform` is initialised to one element which is an instan
|
||||
- A trigger BoxCollider is added to the `DroppletCube` with a size of Vector3.one * 0.01. All collisions with it and the player.entity.`ccol` or the outer BoxCollider are ignored
|
||||
|
||||
After:
|
||||
|
||||
- `vectordata[0]` is incremented by the entity.`startpos`
|
||||
- `internalparticle` is initialised to a single element which is the SpriteBounce of a instance of `Prefabs/Objects/WaterBubble` which is then childed to the entity.`sprite` and has a local position of Vector3.up / 2
|
||||
- entity.`rigid` gets its gravity enabled with rotation frozen and entity.`onground` set to false
|
||||
@@ -49,6 +51,7 @@ What follows is logic that depends on the `actionfrequency` 3 different cooldown
|
||||
|
||||
### `actionfrequency` cooldowns
|
||||
Here is what the different array elements mean:
|
||||
|
||||
- `actionfrequency[0]`: UNUSED (It always stays to -1100 and never changes)
|
||||
- `actionfrequency[1]`: The max cooldown before the dropplet is moved to entity.`startpos` which is hardcoded to 600.0
|
||||
- `actionfrequency[2]`: The cooldown before doing any of this logic which means it serve as a throttle. Defaults to `data[2]`
|
||||
@@ -56,11 +59,13 @@ Here is what the different array elements mean:
|
||||
Nothing in this section happens if `actionfrequency` hasn't expired yet besides the value being decremented by framestep. This effectively throttles main updates to only happen every `data[0]` frames.
|
||||
|
||||
If we aren't being throttled, this is where `actionfrequency[1]` comes into play. If it hasn't expired yet and the entity y position is -25.0 or above, then `actionfrequency[1]` is decremented by framestep. Otherwise, it means the cooldown expired, the dropplet dropped to \< -25 or it was placed offscreen by OnTriggerEnter as a result of touching the ground or being frozen. In that case, the dropplet is reset back to its starting position by doing the following:
|
||||
|
||||
- The position is set to entity.`startpos`
|
||||
- `actionfrequency[1]` is reset to 600.0 which allows the cycle to restart
|
||||
- entity.`rigid` velocity gets zeroed out without kinematic mode
|
||||
|
||||
From there the following always happen:
|
||||
|
||||
- [LockRgid(false)](../../EntityControl/EntityControl%20Methods.md#lockrigid) is called on the entity
|
||||
- entity.`rigid` gets its rotation frozen
|
||||
|
||||
@@ -73,13 +78,14 @@ We only proceed if `data[3]` exists and is above 0.
|
||||
This is where the new `actioncooldown` value is managed. It was already decremented earlier so the only logic here is when it goes below 100.0 every 3 frames and when it expires.
|
||||
|
||||
If it's below 100.0 every 3 frames:
|
||||
|
||||
- The `IceMelt` sound effect is played at `internaltransform[0]` (the actual ice cube) with the volume being that transform's sound distance * 2.0 adjusted by the game's volume settings.
|
||||
- The DialogueAnim of the ice cube targetscale is set to Vector3.zero to make it shrink to nothing at a speed of 0.01
|
||||
|
||||
If it's expired, the ice cube is shattered via ShatterDroppletIce and ServerGeizer is called on the ice cube's Hornable.
|
||||
|
||||
## LateUpdate (Non `dummy`, the entity is `incamera` and not `iskill`)
|
||||
Normally under these circumstances, If the y position is less than the map.`ylimit`, the the position is set to the entity.`startpos` and DeathSmoke particles are played at the entity.`sprite` position if it isn't `dead` and the [animid](../../Enums%20and%20IDs/AnimIDs.md) isn't negative (it is defined).
|
||||
Normally under these circumstances, If the y position is less than the map.`ylimit`, the the position is set to the entity.`startpos` and DeathSmoke particles are played at the entity.`sprite` position if it isn't `dead` and the [animid](../../../Enums%20and%20IDs/AnimIDs.md) isn't negative (it is defined).
|
||||
|
||||
However, `Dropplet` are exempt from the logic above so they aren't bound by the map.`ylimit`.
|
||||
|
||||
@@ -89,22 +95,23 @@ This does nothing if the other gameObject tag isn't `Icecle` or `IceRadius`.
|
||||
If `hit` is true, the `IceShatter` particle is played at the `internaltransform[0]` position and the `IceBreak` sound is played at the same position with the volume being the sound distance of the position adjusted for the game's volume * 1.5. Finally, it also causes ServerGeizer to be called on the `internaltransform[0]`'s Hornable.
|
||||
|
||||
The following occurs:
|
||||
|
||||
- `hit` is set to true
|
||||
- `actionfrequency[0]` is set to -1100.0
|
||||
- `actionfrequency[1]` is set to 600.0
|
||||
- `internaltransform[0]` gets some adjustements:
|
||||
- Its position gets set to the other position + (0.0, 0.25, 0.0)
|
||||
- It gets childed to the map
|
||||
- Its local scale gets set to Vector3.zero
|
||||
- Its Hornable `ingeizer` gets set to null
|
||||
- Its DialogueAnim is enabled with a `shrinkspeed` of 0.1 and a `targetscale` of (1.5, 1.5, 1.5)
|
||||
- Its RigidBody gets its velocity zeroed out and put out of kinematic mode
|
||||
- Its position gets set to the other position + (0.0, 0.25, 0.0)
|
||||
- It gets childed to the map
|
||||
- Its local scale gets set to Vector3.zero
|
||||
- Its Hornable `ingeizer` gets set to null
|
||||
- Its DialogueAnim is enabled with a `shrinkspeed` of 0.1 and a `targetscale` of (1.5, 1.5, 1.5)
|
||||
- Its RigidBody gets its velocity zeroed out and put out of kinematic mode
|
||||
- If the `collisionammount` is less than 2, the `Freeze` sound is played at 0.6 volume
|
||||
- `collisionammount` is incremented
|
||||
- If `data[2]` is 1 (otherwise, the position is set to offscreen at (0.0, -2000.0, 0.0)):
|
||||
- If `data[3]` exists and is above 0, `actioncooldown` is set to `data[3]`
|
||||
- The entity.`rigid` is put in kinematic mode
|
||||
- The position is set to offscreen at (0.0, -2000.0, 0.0) in 0.1 seconds
|
||||
- If `data[3]` exists and is above 0, `actioncooldown` is set to `data[3]`
|
||||
- The entity.`rigid` is put in kinematic mode
|
||||
- The position is set to offscreen at (0.0, -2000.0, 0.0) in 0.1 seconds
|
||||
- `actionfrequency[2]` is set to `data[0]`
|
||||
|
||||
## OnTriggerEnter if the other gameObject layer is `Ground` or `NoDigGround`
|
||||
@@ -112,8 +119,8 @@ This does nothing if the other gameObject tag is `DroppletPass` (This would have
|
||||
|
||||
- `actionfrequency[1]` is set to 600.0
|
||||
- If the entity.`rigid` is not in kinematic mode, the following depends on `internalparticle[0]`:
|
||||
- If it is null, it is initialised to a `WaterSplash` ParticleSystem being played at this object position with angles of (-90.0, 0.0, 0.0) and it is then parented to the map.
|
||||
- If it wasn't null, its position is set to this object position and Play is called on it
|
||||
- If it is null, it is initialised to a `WaterSplash` ParticleSystem being played at this object position with angles of (-90.0, 0.0, 0.0) and it is then parented to the map.
|
||||
- If it wasn't null, its position is set to this object position and Play is called on it
|
||||
- If we aren't in a `pause` and the `startlife` is over 60.0 frames, the `WaterSplash` sound is played at this object position with a volume of the entity sound distance adjusted for the volume settings and multipled by `vectordata[1].z` if it wasn't 0.0.
|
||||
- The entity.`rigid` is put in kinematic mode
|
||||
- The position is set to be offscreen at (0.0, -2000.0, 0.0)
|
||||
@@ -124,12 +131,14 @@ This does nothing if the other gameObject tag is `DroppletPass` (This would have
|
||||
This logic only matters if the method was called as a result of MapControl.Start, MapControl.RefreshInsides and BattleControl.ReturnToOverworld.
|
||||
|
||||
If `data[2]` is 0 or `hit` is false:
|
||||
|
||||
- entity.`rigid` gets its velocity zeroed without kinematic and with gravity
|
||||
- entity.`onground` is set to false
|
||||
- If entity.`originalmap` is the current one, the dropplet is childed to the map
|
||||
|
||||
## ShatterDroppletIce
|
||||
This is a public method that is practically called in a wide variety of places, but it only contains logic pertinent to this object type. It shatters the ice cube by doing the following:
|
||||
|
||||
- `hit` is set to false which makes the game no longer recognise the ice cube exists
|
||||
- `IceShatter` particle is played at the ice cube's position + (0.0, 1.0, 0.0) with angles (-90.0, 0.0, 0.0) for 1.0 second
|
||||
- The `IceBreak` sound effect is played at the ice cube's position with the volume being the ice cube sound distance adjusted by the game volume settings
|
||||
@@ -144,6 +153,7 @@ This component is only used for this object type on `internaltransform[0]` (the
|
||||
For the sake of brevety, the component won't be fully documented, but a summary of the methods is provided here.
|
||||
|
||||
To properly add the Hornable, SetUp must be called and in practice, it's always called with the same parameters on this NPCContol's SetUp:
|
||||
|
||||
- pushammount is (`vectordata[1].x`, `vectordata[1].y`)
|
||||
- pusherenabled is false, but then overriden to true on the component's Start (prevents it to be affected by a `pusher` collider on an [NPC](../NPCType.md#npc))
|
||||
- dashbreak is true (this is unused so it does nothing)
|
||||
@@ -152,11 +162,13 @@ To properly add the Hornable, SetUp must be called and in practice, it's always
|
||||
On its Start, the main thing that happens is the tag is set to `Hornable` (allows PlayerControl to get a green ! emoticon when getting 2.5 or lower distance from the grass for 5 frames), a HelpArrow is setup with a cyan color and a rotater object is created childed to the ice cube (this is used later when `data[4]` gets involved).
|
||||
|
||||
On its LateUpdate, the main things that happens are:
|
||||
|
||||
- Some logic where the ice cube is visually displaced when the ice cube is in a [Geizer](Geizer.md)
|
||||
- The frictions are managed here (basically full friction when at rest, no frictions otherwise)
|
||||
- Enforcing that the cube cannot be more than 150.0 frames in the air or its x and z velocity will be zeroed out and forced to be on the ground
|
||||
|
||||
On its OnTriggerEnter, there are multiple possible interactions depending on the other collider tag:
|
||||
|
||||
- `BeetleHorn`: This means the cube will be launched. The launch is done by using pushammount.x for the x and z axises and pushammount.y for the y axis as the new velocity adjusted by the actual direction the player is at so it launches away from it. However, this can be skewed if `data[4]` exists and is 1 where the actual direction is snapped to the closest 8 cardinal directions relative to the camera (this is done using the rotater object as it's set to look at the player)
|
||||
- `IceBreak`: the player.entity.`hitwall` is set to true and ShatterDroppletIce is called on the NPCControl
|
||||
- `Platform` or `PlatformNoClock`: The ice cube can get childed to the platform (or [Geizer](Geizer.md)) so it moves with it. This is also done in OnCollisionEnter. This is undone in OnTriggerExit when applicable
|
||||
|
||||
@@ -12,6 +12,7 @@ An [event](../../../Enums%20and%20IDs/Events.md) trigger zone. It can either unc
|
||||
|
||||
## Setup
|
||||
A few adjustements occurs:
|
||||
|
||||
- The entity.`alwaysactive` is set to true
|
||||
- The gameObject's isStatic is set to true
|
||||
- The entity.`rigid` is placed in kinematic mode without gravity
|
||||
@@ -28,6 +29,7 @@ Finally, this object gets destroyed.
|
||||
|
||||
## OnTriggerStay
|
||||
This does nothing if any of the following is true:
|
||||
|
||||
- The other gameObject isn't the player
|
||||
- We are `inevent`
|
||||
- We are in a `pause`
|
||||
@@ -36,6 +38,7 @@ This does nothing if any of the following is true:
|
||||
The [regionalflag](../../../Flags%20arrays/Regionalflags.md) slot at `regionalflags` and the [flag](../../../Flags%20arrays/flags.md) slot at `activationflag` are set to true.
|
||||
|
||||
If we aren't in a `minipause`, a WaitForEvent coroutine starts which does the following:
|
||||
|
||||
- `hit` is set to true (this prevents a second trigger)
|
||||
- We enter a `minipause`
|
||||
- Yield frames until `switchcooldown` expires
|
||||
|
||||
@@ -21,24 +21,24 @@ A water or honey geizer that can be frozen using Leif's Freeze and it can elevat
|
||||
- The gameObject layer to 0 (Default).
|
||||
- The `scol` is disabled
|
||||
- `actionfrequency`: is initialised to 2 elemenst :
|
||||
- 0: Random.Range(1.0, 10.0) (this is a random phase shift to the geizer oscillation)
|
||||
- 1: 0.0 (this is a DeltaTime accumulator for use in the geizer oscillation)
|
||||
- 0: Random.Range(1.0, 10.0) (this is a random phase shift to the geizer oscillation)
|
||||
- 1: 0.0 (this is a DeltaTime accumulator for use in the geizer oscillation)
|
||||
- `actioncooldown`: set to -1100.0 (meaning the first update cycle will be treated as if we had an expired cooldown since more than 1 update cycle)
|
||||
- A geizer prefab is instantiated from the path `Prefabs/Objects/Geizer` followed by `data[0]` if applicable. The geizer is childed to the entity's `sprite` and has its local position set to Vector3.zero.
|
||||
- `internaltransform` is initialised to 5 elements:
|
||||
- 0: The first child of the geizer's root (The root of the main geizer object)
|
||||
- 1: The second child of the geizer's root (the root of the frozen geizer object)
|
||||
- 2: The first child of the geizer's first child (the top of the main geizer object)
|
||||
- 3: The second child of the geizer's first child (the spout at the bottom of the main geizer's object)
|
||||
- 4: The first child of the geizer's second child (the frozen spout at the bottom of the frozen geizer object)
|
||||
- 0: The first child of the geizer's root (The root of the main geizer object)
|
||||
- 1: The second child of the geizer's root (the root of the frozen geizer object)
|
||||
- 2: The first child of the geizer's first child (the top of the main geizer object)
|
||||
- 3: The second child of the geizer's first child (the spout at the bottom of the main geizer's object)
|
||||
- 4: The first child of the geizer's second child (the frozen spout at the bottom of the frozen geizer object)
|
||||
- entity.`model` scale is multiplied by a 1/10 of `dialogues[2].x`
|
||||
- entity.`alwaysactive` is set to true
|
||||
- entity.`model` tag is set to `PlatformNoClock`
|
||||
- If entity.`originalid` is the `ElectroPlatform` [AnimID](../../../Enums%20and%20IDs/AnimIDs.md), a GlowTrigger is added on the first child of the `model`:
|
||||
- `getactivecolorfromstart` is set to true
|
||||
- `parent` is set to this NPCControl
|
||||
- `glowparts` is initialised to a single element corresponding to the MeshRenderer of the first child of the `model`
|
||||
- `electime` is initialised to 260.0 unless `dialogues[2].y` exists and isn't 0 where it will take that value instead
|
||||
- `getactivecolorfromstart` is set to true
|
||||
- `parent` is set to this NPCControl
|
||||
- `glowparts` is initialised to a single element corresponding to the MeshRenderer of the first child of the `model`
|
||||
- `electime` is initialised to 260.0 unless `dialogues[2].y` exists and isn't 0 where it will take that value instead
|
||||
|
||||
## Update
|
||||
The `internaltransform[3]` (the bottom spout of the main geizer object) gets its local scale set to Vector3.one. If this is the first Update, `initialrender` is initialised to a single element being the MeshRenderer of the spout of the geizer object. This MeshRenderer is then disabled.
|
||||
@@ -46,7 +46,7 @@ The `internaltransform[3]` (the bottom spout of the main geizer object) gets its
|
||||
From there, the geizer can be active or inactive. It's active if `data[1]` doesn't exist, is -1 or the map entity with the id being `data[1]` exists with a `hit` value of true. It is inactive otherwise. This changes the rest of the update cycle.
|
||||
|
||||
### Inactive updates
|
||||
In the case where the geizer shouldn't be active, [GeizerBreak](../GeizerBreak.md) is called if the `actioncooldown` hasn't expired yet (it is also set to 0.0 in this case). This is followed by the position being set to a lerp from the existing one to the entity's `startpos` - the transform's up vector * 10.0 with a factor of 0.025 * the game's frametime. This basically makes the geizer slowly retract itself such that it's not visible because it would be under the floor or inside a wall.
|
||||
In the case where the geizer shouldn't be active, GeizerBreak is called if the `actioncooldown` hasn't expired yet (it is also set to 0.0 in this case). This is followed by the position being set to a lerp from the existing one to the entity's `startpos` - the transform's up vector * 10.0 with a factor of 0.025 * the game's frametime. This basically makes the geizer slowly retract itself such that it's not visible because it would be under the floor or inside a wall.
|
||||
|
||||
### Active update
|
||||
If the `startlife` is above 20.0 frames and `hit` is false, `hit` is set to true and the ParticleSystem of `internaltransform[3]` (the spout of the main geizer) is set to play which is some water splashing.
|
||||
@@ -63,25 +63,27 @@ From there, there are 3 cases: the `actioncooldown` hasn't expired, it expired l
|
||||
|
||||
#### `actioncooldown` expired since the last Update cycle
|
||||
If the `actioncooldown` expired since the last cycle (tested by checking it is 0.0 or below, but above -1000.0):
|
||||
|
||||
- `internaltransform[0]` is activated (the main geizer object)
|
||||
- `internaltransform[1]` is deactivated (the frozen geizer object)
|
||||
- `internaltransform[3]` is activated (the spout at the bottom of main geizer object)
|
||||
- The `boxcol` is enabled if it is present
|
||||
- If `startlife` is 15.0 or above, [GeizerBreak](../GeizerBreak.md) is called
|
||||
- If `startlife` is 15.0 or above, GeizerBreak is called
|
||||
- The ParticleSystem of `internaltransform[3]` (the spout at the bottom of the water object) is set to play which is some water splashing.
|
||||
- The entity.`sound` is set to no longer loop
|
||||
- `actioncooldown` is set to -1100.0 which changes further update cycles to have the cooldown expired since more than 1 cycle.
|
||||
|
||||
#### `actioncooldown` expired more than 1 Update cycle ago
|
||||
If the `actioncooldown` expired more than 1 cycle ago (checked by being below -1000.0):
|
||||
|
||||
- `internaltransform[2]` (the top of the main geizer object) is set to rotate by 5.0 degrees in the z axis (this is the vertical one due to the pivot point being rotated)
|
||||
- `internaltransform[3]` (the spout at the bottom of the water object) is set to rotate by -5.0 degrees in the y axis
|
||||
- The `boxcol` center is set to (0.0, 3.0 + the root geizer main object y position, 0.0) which elevates it slightly above its position
|
||||
- The geizer's root position (the parent of `internaltransform[0]`) is set to a lerp from the existing one to the entity. `startpos` + the normalized up vector of the transform * Mathf.Sin(`actionfrequency[1]` * `vectordata[0].x` + `actionfrequency[0]`) * `vectordata[0].y` with a factor of the 1/10 of the game's frametime. This oscillates the geizer's:
|
||||
- `vectordata[0].y` is the magnitude of the sine wave, it tells half of the full range between the lowest point the geizer will go and the higest
|
||||
- `actionfrequency[1]` is the time in seconds accumulated since SetUp so this scales the Sin through time
|
||||
- `actionfrequency[2]` is a phase shift that's been determined randomly on SetUp
|
||||
- `vectordata[0].x` is 1/6 of the frequency
|
||||
- `vectordata[0].y` is the magnitude of the sine wave, it tells half of the full range between the lowest point the geizer will go and the higest
|
||||
- `actionfrequency[1]` is the time in seconds accumulated since SetUp so this scales the Sin through time
|
||||
- `actionfrequency[2]` is a phase shift that's been determined randomly on SetUp
|
||||
- `vectordata[0].x` is 1/6 of the frequency
|
||||
- `actionfrequency[1]` is incremented by Time.deltaTime
|
||||
- If the entity's `sound` wasn't playing, [PlaySound](../../EntityControl/EntityControl%20Methods.md#PlaySound) is called with the `Waterfall1` clip at 0.075 volume and the entity.`sound` is set to loop
|
||||
- If `data[2]` is present and 1 and there is a map.lastwater, the y component of the `internaltransform[3]` position (the spout at the bottom of the main geizer object) is set to map.`lastwater` y position. This basically means the spout will be positioned on the map's water Hazards level.
|
||||
@@ -91,15 +93,16 @@ If the `actioncooldown` expired more than 1 cycle ago (checked by being below -1
|
||||
- `internaltransform[3]` (the spout of the main geizer object) has its scale set to Vector3.One
|
||||
- A Raycast is performed from the geizer position + (0.0, 10.0, 0.0) headed down with max 10.0 distance only accepting layers of `Ground` or `NoDigGround`.
|
||||
- If `attacking` is false (this is the first applicable LateUpdate cycle), it is set to true after a Fader component is added to the gameObject with:
|
||||
- forcestayonpause to true
|
||||
- childtied to true
|
||||
- fadedistance to 0.0
|
||||
- pivotoffset to (0.0, the point.y of the collision done earlier or 0.0 if there wasn't a collision - entity.`startpos`, 0.0)
|
||||
- forcestayonpause to true
|
||||
- childtied to true
|
||||
- fadedistance to 0.0
|
||||
- pivotoffset to (0.0, the point.y of the collision done earlier or 0.0 if there wasn't a collision - entity.`startpos`, 0.0)
|
||||
- If `data[3]` is 1 and `startlife` is less than 20.0, the position is set to the entity.`startpos` - the up vector of the geizer * 10.0. This places the geizer such that it will be under the floor / inside its wall very soon after map load
|
||||
- If there was a collision with the raycast earlier, the position of `internaltransform[3]` (the spout of the main geizer object) is set to the hit point of the raycast and it also gets childed to the entity.`sprite`. This basically ensures the spout is placed where the ground actually is and to ensure it doesn't move with the geizer, it's childed in such a way that it is a sibling of the geizer so it stays there independently of the geizer movements
|
||||
|
||||
## OnTriggerEnter
|
||||
There are 4 branches here:
|
||||
|
||||
- The other gameObject tag is `Icecle`, `Icefall` or `IceRadius` and `data[4]` doesn't exist or is 0
|
||||
- The other gameObject tag is `BeetleHorn` or `BeetleDash` and the `actioncooldown` hasn't expired yet (meaning the geizer is frozen)
|
||||
- The other gameObject tag is `DroppletCube` and the `actioncooldown` expired (meaning the geizer isn't frozen)
|
||||
@@ -107,29 +110,29 @@ There are 4 branches here:
|
||||
|
||||
### Ice collider logic
|
||||
- If the `moveobj` is present (meaning a [Dropplet](Dropplet.md) ice cube is on the geizer):
|
||||
- LaunchObject is called with it using a random vector between (0.0, -15.0, 0.0) and (0.0, 15.0, 0.0)
|
||||
- The parent of the ice cube is set to the current map
|
||||
- [ServerGeizer](Dropplet.md#servergeizer) is called onm the `moveobj` Hornable which setups the cube to be on the geizer snapped to it
|
||||
- LaunchObject is called with it using a random vector between (0.0, -15.0, 0.0) and (0.0, 15.0, 0.0)
|
||||
- The parent of the ice cube is set to the current map
|
||||
- [ServerGeizer](Dropplet.md#servergeizer) is called onm the `moveobj` Hornable which setups the cube to be on the geizer snapped to it
|
||||
- If the `actioncooldown` expired (meaning the geizer isn't frozen):
|
||||
- The `boxcol` is disabled if present
|
||||
- `internaltransform[0]` (the main geizer object) gets disabled
|
||||
- `internaltransform[3]` (the spout of the main geizer object) gets disabled
|
||||
- `internaltransform[1]` (the frozen geizer object) gets enabled
|
||||
- `internaltransform[4]` (the spout of the frozen geizer object) gets enabled except if the current [map](../../../Enums%20and%20IDs/Maps.md) is `UpperSnekGeizerRoom` where it is disabled
|
||||
- The entity.`sound` is stopped and placed at the begining of the playback
|
||||
- The `Freeze` sound is played at 0.5 volume
|
||||
- The `boxcol` is disabled if present
|
||||
- `internaltransform[0]` (the main geizer object) gets disabled
|
||||
- `internaltransform[3]` (the spout of the main geizer object) gets disabled
|
||||
- `internaltransform[1]` (the frozen geizer object) gets enabled
|
||||
- `internaltransform[4]` (the spout of the frozen geizer object) gets enabled except if the current [map](../../../Enums%20and%20IDs/Maps.md) is `UpperSnekGeizerRoom` where it is disabled
|
||||
- The entity.`sound` is stopped and placed at the begining of the playback
|
||||
- The `Freeze` sound is played at 0.5 volume
|
||||
- The `actioncooldown` gets set to `vectordata[0].z`, but if the Extra Freeze [medal](../../../Enums%20and%20IDs/Medal.md) is equipped, the value is multiplied by 3 before assigning it
|
||||
|
||||
### Kabbu collider logic while the geizer is frozen
|
||||
- The player entity `hitwall` is set to true
|
||||
- The `actioncooldown` is set to 0.0
|
||||
- [GeizerBreak](../GeizerBreak.md) is called
|
||||
- GeizerBreak is called
|
||||
- The `boxcol` is disabled if it is present
|
||||
|
||||
### [Dropplet](Dropplet.md) cube collider logic while the geizer isn't frozen
|
||||
- If the `moveobj` is present (there was already a dropplet ice cube on the geizer):
|
||||
- LaunchObject is called with it using a random vector between (-5.0, -10.0, 0.0) and (5.0, 10.0, 0.0)
|
||||
- [ServerGeizer](Dropplet.md#servergeizer) is called onm the `moveobj` Hornable which setups the cube to be on the geizer snapped to it
|
||||
- LaunchObject is called with it using a random vector between (-5.0, -10.0, 0.0) and (5.0, 10.0, 0.0)
|
||||
- [ServerGeizer](Dropplet.md#servergeizer) is called onm the `moveobj` Hornable which setups the cube to be on the geizer snapped to it
|
||||
- The RigidBody of the other's parent gets its velocity zeroed out without gravity in kinematic mode
|
||||
- The parent of the other dropplet is set to `internaltransform[0]` (The main geizer object)
|
||||
- `moveobj` is assigned to the other dropplet
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Item
|
||||
A collectable [item](../../../Enums%20and%20IDs/Items.md) or crystal berry bound to a [crystalbfflags](../../../Enums%20and%20IDs/crystalbfflags.md) slot whose item id is the entity.`animid` field. This extends the logic of an [item entity](../../EntityControl/Item%20entity.md).
|
||||
A collectable [item](../../../Enums%20and%20IDs/Items.md), [medal](../../../Enums%20and%20IDs/Medal.md) or crystal berry bound to a [crystalbfflags](../../../Enums%20and%20IDs/crystalbfflags.md) slot whose item id is the entity.`animid` field. This extends the logic of an [item entity](../../EntityControl/Item%20entity.md).
|
||||
|
||||
## Data Arrays
|
||||
- `data[0]`: The [item type](../../EntityControl/Item%20entity.md#item-types). NOTE: if the `animid` is a money item id (`MoneySmall`, `MoneyMedium` or `MoneyBig`), this should always be 0 or 1 (standard or key item) because if it's not, the collection logic won't work as expected
|
||||
@@ -26,6 +26,7 @@ This is a special way to create an [EntityControl](../../EntityControl/EntityCon
|
||||
The very first thing this does is call [CreateNewEntity](../../EntityControl/EntityControl%20Methods.md#createnewentity) with the name `tempitem` and add an NPCControl to it.
|
||||
|
||||
The rest is logic specific to CreateItem:
|
||||
|
||||
- `objecttype` is set to `Item`
|
||||
- `entitytype` is set to `Object`
|
||||
- entity.`item` is set to true making it an [item entity](../../EntityControl/Item%20entity.md)
|
||||
@@ -55,11 +56,12 @@ Also, just like `SemiNPC` items, no changes to the entity.`rigid` mass happens s
|
||||
- entity.`ccol` bounciness is set to 0.75
|
||||
- The layer is set to 0 (default)
|
||||
- All collisions between entity.`ccol` and these entity's `ccol` are ignored:
|
||||
- Objects with tag `PFollower`
|
||||
- Any other Item objects (excludes `SemiNPC`)
|
||||
- Any playerdata except the first one
|
||||
- Objects with tag `PFollower`
|
||||
- Any other Item objects (excludes `SemiNPC`)
|
||||
- Any playerdata except the first one
|
||||
|
||||
If the entity.`animid` is 3 (which means it's a crystal berry) and `tempobject` is false, then this is setup as a crystal berry which starts by setting `data[0]` to `data[3]` (meaning `data[0]` is now the Crystal Berry id which is fine because entity.`animid` already tells it's a Crystal Berry). If it was obtained (the id is contained in `data[3]`), then the entity.`iskill` is set to true. Otherwise, adjustements on the entity are performed:
|
||||
|
||||
- entity.`animstate` is set to the `regionaflag` NOTE: this is likely an error, but it doesn't matter because the [crystalbfflags](../../../Enums%20and%20IDs/crystalbfflags.md) slot is already saved in `data[0]` and it is that value that will be used
|
||||
- entity.`sprite` local position is set to Vector3.zero
|
||||
- AddModel is called with path `Prefabs/Objects/CrystalBerry` without offset
|
||||
@@ -75,25 +77,28 @@ Just like `SemiNPC` items, the `colliderheight` is set to 1.0 and the entity.`cc
|
||||
This section applies for any [item entity](../../EntityControl/Item%20entity.md), but it effectively apply to this object type. Unlike `SemiNPC` items however, this gets the full version of the logic.
|
||||
|
||||
If the `beerang` isn't null (meaning the [beemerang](Beemerang.md) caught this item), the following occurs:
|
||||
|
||||
- The `timer` is set to 300.0 if it was -1
|
||||
- The absolute position is set to the `beerang` one + Vector3.Up
|
||||
- The entity's Unifx gets called if it was a `fixedentity`
|
||||
|
||||
All collisions gets ignored between the `secondcoll` and the player.entity.`ccol` if the player is present and the `touchcooldown` hasn't expired yet. Otherwise, if the `touchcooldown` isn't exactly -9999.0, the collisions gets unignored and `toochcooldown` gets set to -9999.0 (so it doesn't unignore again). If neither happened, the entity.`ccol` is enabled.
|
||||
|
||||
If the entity.`onground` is true, [Jump](../EntityControl/EntityControl%20Methods.md#jump) is called on it with the absolute value of its current `rigid` y velocity. It will also increment `bounces` if it hasn't reached 3 yet on top of playing the `ItemBounce0` sound effect (or `ItemBounce1` if it's a Crystal Berry) if the `startlife` is above 15 frames.
|
||||
If the entity.`onground` is true, [Jump](../../EntityControl/EntityControl%20Methods.md#jump) is called on it with the absolute value of its current `rigid` y velocity. It will also increment `bounces` if it hasn't reached 3 yet on top of playing the `ItemBounce0` sound effect (or `ItemBounce1` if it's a Crystal Berry) if the `startlife` is above 15 frames.
|
||||
|
||||
If by then, `bounces` has reached 3, [StopForceMove](../EntityControl/EntityControl%20Methods.md#StopForceMove) is called on the entity.
|
||||
If by then, `bounces` has reached 3, [StopForceMove](../../EntityControl/EntityControl%20Methods.md#stopforcemove) is called on the entity.
|
||||
|
||||
If the entity.`sprite` is present, then the `timer` logic proceeds:
|
||||
|
||||
- If the `timer` has yet to expire and we aren't in a `minipause` or `pause`, the timer is decremented according to the frametime, but it is clamped from 0.0 to infinity. Otherwise, if the `timer` expired, this GameObject gets destroyed
|
||||
- If the `timer` is between -1.0 and 100.0 exclusive and we aren't in a `minipause` or `inevent`, the entity.`sprite` enablement gets toggled. Otherwise, the entity.`sprite` is enabled. This logic blinks the sprite when less than 100 frames are left on the `timer`
|
||||
|
||||
## OnTriggerEnter if the other collider is the player
|
||||
If we aren't in a `pause` or `minipause`, the `insideid` matches the current one and the `timer` is exactly -1.0 or above 1.0, a [CheckItem](../CheckItem.md) coroutine is started and `collisionammount` is incremented.
|
||||
If we aren't in a `pause` or `minipause`, the `insideid` matches the current one and the `timer` is exactly -1.0 or above 1.0, a CheckItem coroutine is started and `collisionammount` is incremented.
|
||||
|
||||
## OnTriggerEnter main segment
|
||||
The `beerang` is set to the other transform if all of the following are true (this makes the `Beemerang` catch the item):
|
||||
|
||||
- The other gameObject tag is `BeeRang` (meaning the other collider is the [Beemerang](Beemerang.md))
|
||||
- `data[2]` is either not present or it is and it's value is 0 (meaning it's a standard item)
|
||||
- `beerang` was null (the `Beemerang` didn't already caught an item)
|
||||
@@ -137,18 +142,20 @@ This logic is quite complex and has different behaviors depending on the entity.
|
||||
|
||||
#### Hold the player until they get `onground`
|
||||
The logic first starts to handle the case where the player is still in the air:
|
||||
|
||||
- player.`lockkeys` is set to true (disable most input processing on PlayerControl)
|
||||
- As long as player.entity.`onground` is false:
|
||||
- player.entity.`rigid` x/z velocity is zeroed out
|
||||
- instance.`minipause` is set to true
|
||||
- The position of the item is set to offscreen at (0.0, 999.0, 0.0)
|
||||
- If we have been on this yield loop for 300.0 frames or more, we force exit it by setting the player position to its `lastpos` with DeathSmoke particle playing at the player position
|
||||
- A local framecounter is incremented by `framestep` which only takes effect once it reaches 300.0 as outlined in the step above
|
||||
- A frame is yielded
|
||||
- player.entity.`rigid` x/z velocity is zeroed out
|
||||
- instance.`minipause` is set to true
|
||||
- The position of the item is set to offscreen at (0.0, 999.0, 0.0)
|
||||
- If we have been on this yield loop for 300.0 frames or more, we force exit it by setting the player position to its `lastpos` with DeathSmoke particle playing at the player position
|
||||
- A local framecounter is incremented by `framestep` which only takes effect once it reaches 300.0 as outlined in the step above
|
||||
- A frame is yielded
|
||||
- player.`lockkeys` is set to false (unlocks most input processing of PlayerControl)
|
||||
|
||||
#### Item collection perparation
|
||||
From there, the actual item collection can now take place:
|
||||
|
||||
- `beerang` is set to null (detaches the item off the [Beemerang](Beemerang.md) if it was attached)
|
||||
- entity.`spin` gets zeroed out
|
||||
- entity.`sprite` angles gets set to Vector3.zero
|
||||
@@ -162,22 +169,23 @@ From there, the actual item collection can now take place:
|
||||
|
||||
#### Item type specifics
|
||||
What happens next depends on entity.`animid` (the item type) and it mainly sets the `back` material color, sets `flagstring` 0, `flagstring` 1 and other exclusive logic to an item type:
|
||||
|
||||
- 0 or 1 (standard or key [item](../../../Enums%20and%20IDs/Items.md)):
|
||||
- `flagstring` 0 is set to the name and `flagstring` 1 to the prepender of the corresponding item defined in [items data](../../../TextAsset%20Data/Items%20data.md#items-data) using the entity.`animstate` as the item id.
|
||||
- It also sets the `back`'s material color to 00B2B2 (cyan) if it's a standard item, FF4C66 (bright red) if it's a key item
|
||||
- `flagstring` 0 is set to the name and `flagstring` 1 to the prepender of the corresponding item defined in [items data](../../../TextAsset%20Data/Items%20data.md#items-data) using the entity.`animstate` as the item id.
|
||||
- It also sets the `back`'s material color to 00B2B2 (cyan) if it's a standard item, FF4C66 (bright red) if it's a key item
|
||||
- 2 ([medal](../../../Enums%20and%20IDs/Medal.md)):
|
||||
- If `flags` 681 (MYSTERY? is enabled) and entity.`animstate` isn't 59 (it's not `Extra Freeze`) or it is, but `flags` 696 (MYSTERY? file started on 1.1.x) is false:
|
||||
- The next mystery medal id is obtained and the value is set to entity.`basestate`, entity.`itemstate`, entity.`animstate` and `flagvar` 0
|
||||
- entity.`overridemovesmoke` is set to true and UpdateItem is called on the entity (to ensure the actual sprite gets updated)
|
||||
- The `back` material color gets set to FF7F00 (bright orange)
|
||||
- `flagstring` 0 is set to a string obtained from taking `menutext[268]` and replacing `i` by the corresponding medal name from [medal data](../../../TextAsset%20Data/Medals%20data.md#badgename-data) using entity.`animstate` as the medal id and by replacing `m` by `menutext[159]` (`Medal`)
|
||||
- `flagstring` 1 is set to the corresponding prepander from [medal data](../../../TextAsset%20Data/Medals%20data.md#badgename-data) using entity.`animstate` as the medal id
|
||||
- If `flags` 681 (MYSTERY? is enabled) and entity.`animstate` isn't 59 (it's not `Extra Freeze`) or it is, but `flags` 696 (MYSTERY? file started on 1.1.x) is false:
|
||||
- The next mystery medal id is obtained and the value is set to entity.`basestate`, entity.`itemstate`, entity.`animstate` and `flagvar` 0
|
||||
- entity.`overridemovesmoke` is set to true and UpdateItem is called on the entity (to ensure the actual sprite gets updated)
|
||||
- The `back` material color gets set to FF7F00 (bright orange)
|
||||
- `flagstring` 0 is set to a string obtained from taking `menutext[268]` and replacing `i` by the corresponding medal name from [medal data](../../../TextAsset%20Data/Medals%20data.md#badgename-data) using entity.`animstate` as the medal id and by replacing `m` by `menutext[159]` (`Medal`)
|
||||
- `flagstring` 1 is set to the corresponding prepander from [medal data](../../../TextAsset%20Data/Medals%20data.md#badgename-data) using entity.`animstate` as the medal id
|
||||
- 3 (Crystal Berry):
|
||||
- The `back` local position is set to (0.0, 0.5, 0.0) and its material color to cyan
|
||||
- entity.`model` y scale is set to 0.1
|
||||
- [crystalbfflags](../../../Enums%20and%20IDs/crystalbfflags.md) whose slot is `data[0]` (used to be `data[3]` which is the slot number) is set to true
|
||||
- `flagstring` 0 is set to `menutext[112]` (`Crystal Berry`)
|
||||
- `flagvar` 14 (amount of Crystal Berries obtained) gets incremented
|
||||
- The `back` local position is set to (0.0, 0.5, 0.0) and its material color to cyan
|
||||
- entity.`model` y scale is set to 0.1
|
||||
- [crystalbfflags](../../../Enums%20and%20IDs/crystalbfflags.md) whose slot is `data[0]` (used to be `data[3]` which is the slot number) is set to true
|
||||
- `flagstring` 0 is set to `menutext[112]` (`Crystal Berry`)
|
||||
- `flagvar` 14 (amount of Crystal Berries obtained) gets incremented
|
||||
|
||||
After this, for any type other than Crystal Berry, [CreateDescWindow](../Notable%20methods/CreateDescWindow.md) without shop is called.
|
||||
|
||||
@@ -185,6 +193,7 @@ For any type, the `ItemGetX` sound is played where X is the entity.`animid` (the
|
||||
|
||||
#### [SetText](../../../SetText/SetText.md) call
|
||||
The next portion setups a SetText call to actually receive the item. The SetText string is built with the following concatenated in order:
|
||||
|
||||
- `|lockmovement||boxstyle,4||halfline||spd,0||anim,-1,4||center|`
|
||||
- `menutext[2]` (`You found |string,1| |color,1||string,0||color,1|!`)
|
||||
- `|stopskip||fwait,0.45||break|`
|
||||
@@ -198,6 +207,7 @@ The next portion setups a SetText call to actually receive the item. The SetText
|
||||
- If `data[1]` exists and isn't negative, `|event,` + `data[1]` + `|` is appended (a [break](../../../SetText/Individual%20commands/Break.md) command appears before the event one if any of the tutorial strings were appended)
|
||||
|
||||
SetText is called with the generated string in [dialogue mode](../../../SetText/Dialogue%20mode.md):
|
||||
|
||||
- [fonttype](../../../SetText/Notable%20states.md#fonttype) of `BubblegumSans`
|
||||
- linebreak of instance.`messagebreak`
|
||||
- No tridimensional
|
||||
@@ -209,12 +219,13 @@ SetText is called with the generated string in [dialogue mode](../../../SetText/
|
||||
|
||||
#### SetText yield
|
||||
This is the final part part of the collection phase:
|
||||
|
||||
- `timer` is set to -1 (so it never times out)
|
||||
- entity.`overrideflip` is set to true
|
||||
- As long as the [message](../../../SetText/Notable%20states.md#message) lock is active:
|
||||
- player.entity.`flip` is set to the value it had before this entire collection phase at the start of CheckItem
|
||||
- player.entity.[animsate](../../EntityControl/Animations/animstate.md) is set to 4 (`ItemGet`)
|
||||
- A frame is yielded
|
||||
- player.entity.`flip` is set to the value it had before this entire collection phase at the start of CheckItem
|
||||
- player.entity.[animsate](../../EntityControl/Animations/animstate.md) is set to 4 (`ItemGet`)
|
||||
- A frame is yielded
|
||||
- If the item isn't `tossed` (it is only when [additemtoss](../../../SetText/Individual%20commands/Additemtoss.md) concluded the player wanted to toss the item), this gameObject is destroyed
|
||||
|
||||
## EntityControl.LateStart
|
||||
@@ -225,5 +236,6 @@ If the NPCControl passed has this type, it returns true which allows it to stay
|
||||
|
||||
## [SetText](../../../SetText/SetText.md)
|
||||
This object type affects SetText if it's the caller:
|
||||
|
||||
- In an [end](../../../SetText/Individual%20commands/End.md) command, if the caller is an `Item`, [Death](../../EntityControl/Notable%20methods/Death.md) is called on the entity
|
||||
- In the [cleanup phase](../../../SetText/Life%20Cycle.md#cleanup), if the caller is an object of this type and its `hit` is true (meaning it's been collected), its gameObject is destroyed.
|
||||
@@ -14,6 +14,7 @@ A spring that makes an entity jump up high via [Jump](../../EntityControl/Entity
|
||||
|
||||
## Setup
|
||||
A few adjustements occurs:
|
||||
|
||||
- The entity.`activeonpause` is set to true
|
||||
- `internalvector` is initialised to 2 elements with the first being `boxcol`.center and the second being (0.0, 555.0, 999.0) which is an offscreen position.
|
||||
- The entity.`alwaysactive` is set to true
|
||||
@@ -24,10 +25,11 @@ A few adjustements occurs:
|
||||
- The `scol` is disabled
|
||||
|
||||
## Update
|
||||
The `boxcol`.center is set to the first `internalvector` (the original `boxcol`.center) if the instance's `itempicked` is false or to the second one (the offscreen position) if it's true. This just places the `boxcol`.center at an hardcoded offscreen position if we are in the process of a [CheckItem](../Notable%20methods/CheckItem.md).
|
||||
The `boxcol`.center is set to the first `internalvector` (the original `boxcol`.center) if the instance's `itempicked` is false or to the second one (the offscreen position) if it's true. This just places the `boxcol`.center at an hardcoded offscreen position if we are in the process of a [CheckItem](Item.md#checkitem).
|
||||
|
||||
## OnTriggerStay
|
||||
This does nothing if any of the following are true:
|
||||
|
||||
- We are in a `pause`
|
||||
- The current [map](../../../Enums%20and%20IDs/Maps.md) is `RubberPrisonGym` while the other gameObject y position is not higher than this object y position
|
||||
- The other gameObject is the player and it is not free (ignoring fly)
|
||||
@@ -35,6 +37,7 @@ This does nothing if any of the following are true:
|
||||
The entity.`overrideflip` is set to true and the other gameObject's entity is obtained.
|
||||
|
||||
For an actual jump to be registered on the spring, the following must all be true:
|
||||
|
||||
- The other entity exists
|
||||
- The other entity is not `iskill`
|
||||
- `data[1]` is 0 or `data[1]` is 1 and the other entity isn't `onground` and its `rigid` has a negative y velocity
|
||||
@@ -49,6 +52,7 @@ From there, the logic differs depending on `data[0]`. At the end of either branc
|
||||
|
||||
#### `data[0]` is 1 ([JumpTo](../../EntityControl/EntityControl%20Methods.md#JumpTo) logic)
|
||||
If the other gameObject is the player, nothing happens here if the `collisionammount` is 100 or above (meaning we already entered this since the last LateUpdate). If it's less than 100 however:
|
||||
|
||||
- The player position is set to this object position + (0.0, 0.75, 0.0)
|
||||
- [JumpTo](../../EntityControl/EntityControl%20Methods.md#JumpTo) is called on the player with the position being `vectordata[1]`, the height being `vectordata[0].x` and the multiplier being 1.0 unless `vectordata[2].x` exists which will make it be the multiplier instead clamped from 1.0 to 99.0.
|
||||
- If `data[2]` isn't negative, MoveInside will be called on the map with the NPCControl that resolves to the map entity id of `data[2]` as the caller without move (this implies that NPCControl is a [DoorSameMap](DoorSameMap.md))
|
||||
@@ -57,10 +61,10 @@ If the other gameObject is the player, nothing happens here if the `collisionamm
|
||||
#### `data[0]` isn't 1 ([Jump](../../EntityControl/EntityControl%20Methods.md#Jump) logic)
|
||||
- The other entity.`springcooldown` is set to true
|
||||
- The other entity.`jumpcooldown` is set to 30.0
|
||||
- If the other gameObject is the player, CancelAction is called on the player keeping the beemerang. On top of this, if `itempicked` is true (we are in a [CheckItem](../Notable%20methods/CheckItem.md) process), the player entity.`onground` is set to true
|
||||
- If the other gameObject is the player, CancelAction is called on the player keeping the beemerang. On top of this, if `itempicked` is true (we are in a [CheckItem](Item.md#checkitem) process), the player entity.`onground` is set to true
|
||||
- Unless we set.`onground` to true earlier, the following occurs:
|
||||
- The entity.`springcooldown` is set to true
|
||||
- [Jump](../../EntityControl/EntityControl%20Methods.md#Jump) is called on the other entity with the height being its `jumpheight` unless `vectordata[0].x` is above 1.0 and the other doesn't have an `npcdata` that is a [RollingRock](RollingRock.md) where `vectordata[0].x` is used as the height instead
|
||||
- The entity.`springcooldown` is set to true
|
||||
- [Jump](../../EntityControl/EntityControl%20Methods.md#Jump) is called on the other entity with the height being its `jumpheight` unless `vectordata[0].x` is above 1.0 and the other doesn't have an `npcdata` that is a [RollingRock](RollingRock.md) where `vectordata[0].x` is used as the height instead
|
||||
|
||||
## Hazards.OnObjectStay
|
||||
If the NPCControl passed has this type, it returns true which allows it to stay in collision with the Hazards.
|
||||
@@ -16,6 +16,7 @@ The `musicrangeanim` of the map is set to the map entity id being created here.
|
||||
|
||||
## Setup
|
||||
A few adjustements occurs:
|
||||
|
||||
- The entity.`alwaysactive` is set to true
|
||||
- The gameObject's isStatic is set to true
|
||||
- The entity.`rigid` is placed in kinematic mode without gravity
|
||||
@@ -25,10 +26,10 @@ A few adjustements occurs:
|
||||
- entity.`activeonpause` is set to true
|
||||
- `data[0]` is overriden to `data[1]`
|
||||
- entity.`sound` properties are initialised:
|
||||
- The clip is set to one loaded using the [Music](../../../Enums%20and%20IDs/Musics.md)'s name at id `data[2]`
|
||||
- The volume to 0.0
|
||||
- The loop to true
|
||||
- Play is called on it
|
||||
- The clip is set to one loaded using the [Music](../../../Enums%20and%20IDs/Musics.md)'s name at id `data[2]`
|
||||
- The volume to 0.0
|
||||
- The loop to true
|
||||
- Play is called on it
|
||||
- `vectordata[1]` is overriden to have its x be 0.0 and its y / z be the end and begin loop points respectively of the corresponding [music data](../../../TextAsset%20Data/Musics%20data.md#musics-data) whose music id is `data[2]`
|
||||
|
||||
## Update
|
||||
|
||||
@@ -5,8 +5,8 @@ A platform that moves on a set path defined by multiple absolute position vector
|
||||
- `data`: The map entities ids to check for their `hit` being true and if any are, it will tell the platform to set its `hit` to true and to start moving along its path in path mode. This is optional, the platform is considered as continually moving as normal without any elements
|
||||
- `vectordata`: The nodes the platform will travel in absolute positioning
|
||||
- `dialogues[0].x`:The meaning depends on the mode:
|
||||
- In path mode, this is the starting node after truncating to int
|
||||
- In loop mode, this is the starting `speedmultiplier` (the starting node index) after truncating to int. This means only \[0.0, 2.0\[ are valid values
|
||||
- In path mode, this is the starting node after truncating to int
|
||||
- In loop mode, this is the starting `speedmultiplier` (the starting node index) after truncating to int. This means only \[0.0, 2.0\[ are valid values
|
||||
- `dialogues[0].y`: The speed multiplier at which the platform moves.
|
||||
- `dialogues[1].x`: if it's 1, it means to place the platform in loop mode by only using the first 2 `vectordata` and disregard the `currentnode` logic
|
||||
- `dialogues[1].y`: The `actioncooldown` to apply when the platform has reached the end of its path and it should go inactive.
|
||||
@@ -25,19 +25,19 @@ A platform that moves on a set path defined by multiple absolute position vector
|
||||
- entity.`model` scale is multiplied by a 1/10 of `dialogues[2].x`
|
||||
- If `dialogues[1].x` is 1 (loop mode) and `dialogues[0].x` is 1 (the starting node is the second one), the `speedmultiplier` is set to 1.0
|
||||
- If `dialogues[1].x` is 0 (path mode):
|
||||
- `currentnode` is set to `dialogues[0].x`
|
||||
- The position is set to the `vectordata` at the `currentnode`
|
||||
- entity.`startpos` is set to the new position
|
||||
- `currentnode` is set to `dialogues[0].x`
|
||||
- The position is set to the `vectordata` at the `currentnode`
|
||||
- entity.`startpos` is set to the new position
|
||||
- If the entity.`originalid` is the `Lilypad` [AnimID](../../../Enums%20and%20IDs/AnimIDs.md):
|
||||
- The `scol` is disabled
|
||||
- the `boxcol` is recreated with trigger and a size of (5.0, 1.0, 5.0) which overrides all the `boxcol` fields obtained when loading the data.
|
||||
- The `scol` is disabled
|
||||
- the `boxcol` is recreated with trigger and a size of (5.0, 1.0, 5.0) which overrides all the `boxcol` fields obtained when loading the data.
|
||||
- entity.`alwaysactive` is set to true
|
||||
- entity.`model` tag is set to `PlatformNoClock`
|
||||
- If entity.`originalid` is the `ElectroPlatform` [AnimID](../../../Enums%20and%20IDs/AnimIDs.md), a GlowTrigger is added on the first child of the `model`:
|
||||
- `getactivecolorfromstart` is set to true
|
||||
- `parent` is set to this NPCControl
|
||||
- `glowparts` is initialised to a single element corresponding to the MeshRenderer of the first child of the `model`
|
||||
- `electime` is initialised to 260.0 unless `dialogues[2].y` exists and isn't 0 where it will take that value instead
|
||||
- `getactivecolorfromstart` is set to true
|
||||
- `parent` is set to this NPCControl
|
||||
- `glowparts` is initialised to a single element corresponding to the MeshRenderer of the first child of the `model`
|
||||
- `electime` is initialised to 260.0 unless `dialogues[2].y` exists and isn't 0 where it will take that value instead
|
||||
|
||||
## Update
|
||||
If entity.`originalid` is the `Lilypad` [AnimId](../../../Enums%20and%20IDs/AnimIDs.md), the `boxcol` if present is kept enabled, otherwise, its enabled will bet set to the `hit` value.
|
||||
@@ -59,6 +59,7 @@ Unless entity.`originalid` is the `Lilypad` [AnimId](../../../Enums%20and%20IDs/
|
||||
|
||||
### Path mode
|
||||
What happens each updates depends on the value of `hit` which gets toggled on and off in a very systematic manner. The details involves many different fields that interacts with each other:
|
||||
|
||||
- `actioncooldown`: The cooldown used to stop movement whenever the platform reaches its last node AND it is considered deactivated. This is refreshed to be `dialogues[1].y` each time the platform goes to a new node with `hit` being set to true.
|
||||
- `speedmultiplier`: The factor to use when lerping the platform positions between nodes. It's set to 0.0 when going to a new node until it reaches 1.0+. It progressively increases by the frametime of the game * `dialogues[0].y` / 1000.0.
|
||||
- `bounces`: The previous node index visited which will be used as the `from` vector when lerping.
|
||||
@@ -82,6 +83,7 @@ When moving the platform, the lerping using will be the standard Vector3.Lerp, b
|
||||
|
||||
## OnTriggerEnter if the other collider is the player
|
||||
There is some dead logic here where nothing happens, but the conditions are all of these being true:
|
||||
|
||||
- The current [area](../../../Enums%20and%20IDs/librarystuff/Areas.md) is `WildGrasslands`
|
||||
- The entity `originalid` is the `Lilypad` [animid](../../../Enums%20and%20IDs/AnimIDs.md)
|
||||
- The player entity is `onground`
|
||||
@@ -97,4 +99,3 @@ Specififcally, the GroundDetector's OnTriggerStay will check if the other collid
|
||||
The Hornable component also does this which is related to the ice cube of a [Dropplet](Dropplet.md). If the other collider has either tag, OnTriggerEnter / OnCollisionEnter will child the other transform to the platform. This is undone on the component's OnTriggerExit if the other collider has either of the tags.
|
||||
|
||||
As for what the entity.`noclock` does, normally, on MainManager.DoClock, the method RefreshPlayer is called when the player is free and it would normally set the `onground` to false and root all playerdata entities (this incidentally has a known issue where the frictions gets toggled off for one frame every second). `noclock` is a field that will prevent this logic from happening so it prevents the rooting of the player to the scene. In the case of the PathPlatform, it means that this logic doesn't happen as long as the player is on the platform AND it is active (the logic is free to do its thing when the platform goes inactive).
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ If the entity.`originalid` is `AncientPressurePlate`, a GlowTrigger is added on
|
||||
If the `activationflag` [flags](../../../Flags%20arrays/flags.md) slot is true, the `hit` is set to true and the `moveobj`'s local position to `vectordata[0]` which sets the plate as pressed and visually renders it so.
|
||||
|
||||
Finally, a few adjustements occurs:
|
||||
|
||||
- The entity.`alwaysactive` is set to true
|
||||
- The gameObject's isStatic is set to true
|
||||
- The entity.`rigid` is placed in kinematic mode without gravity
|
||||
@@ -34,13 +35,14 @@ From there, if `hit` is true, the `moveobj` local position is set to a lerp from
|
||||
|
||||
## OnTriggerStay
|
||||
This does nothing if any of these are true:
|
||||
|
||||
- The other gameObject is the player `beemerang`
|
||||
- The `activationflag` (if it's not -1) refers to a [flag](../../../Flags%20arrays/flags.md) slot whose value is true
|
||||
- All of the following are false:
|
||||
- The other gameObject's Hornable doesn't exist (meaning this isn't an entity.`icecube`)
|
||||
- The other gameObject tag is `PushRock`
|
||||
- `data[0]` is 1 and the other gameObject is the player
|
||||
- `data[1]` is 1 and the other gameObject is an NPCControl with its `icecube` not null
|
||||
- The other gameObject's Hornable doesn't exist (meaning this isn't an entity.`icecube`)
|
||||
- The other gameObject tag is `PushRock`
|
||||
- `data[0]` is 1 and the other gameObject is the player
|
||||
- `data[1]` is 1 and the other gameObject is an NPCControl with its `icecube` not null
|
||||
|
||||
- If `hit` is false, [SwitchSound(true)](../Notable%20methods/SwitchSound.md) is called
|
||||
- The other gameObject's Hornable `onground` is set to true (the entity.`icecube`)
|
||||
@@ -50,12 +52,14 @@ This does nothing if any of these are true:
|
||||
|
||||
## OnTriggerExit
|
||||
This does nothing if the other gameObject is the player `beemerang`, or if none of the following are true:
|
||||
|
||||
- The other gameObject has a Hornable (it's an entity.`icecube`)
|
||||
- The other gameObject tag is `PushRock`
|
||||
- `data[1]` is 1 and the other gameObject has an NPCControl
|
||||
- `data[0]` is 1 and the other gameObject is the player
|
||||
|
||||
The following occurs if the conditions above are met:
|
||||
|
||||
- `hit` is set to false
|
||||
- `actioncooldown` is set to 0.0
|
||||
- [SwitchSound(false)](../Notable%20methods/SwitchSound.md) is called
|
||||
@@ -5,10 +5,10 @@ A rock or a pushable ice cube that can be moved using Kabbu's Horn Slash with co
|
||||
- `data[0]`: UNUSED (was used to enable a limited radius via a special collider)
|
||||
- `data[1]`: If it's 1, the entity.`rigid` constraint are set to none on SetUp, no changes otherwise (This feature is unused under normal gameplay)
|
||||
- `data[2]`: Determines the mode of operation of the object (This is optional, if it doesn't exist, 0 is assumed):
|
||||
- 0: this is a rock that can be moved in any direction by using Kabbu's Horn Slash which launches it in the air before landing
|
||||
- 1: An ice cube that can be moved via sliding only in the x and y axises (This is unused under normal gameplay)
|
||||
- 2: An ice cube that can be moved via sliding only in the z and y axises (This is unused under normal gameplay)
|
||||
- 3: An ice cube that can be moved via sliding only in the x and z axises and that can shatter and respawn if it ever collides with a gameObject having the tag `RockLimit`
|
||||
- 0: this is a rock that can be moved in any direction by using Kabbu's Horn Slash which launches it in the air before landing
|
||||
- 1: An ice cube that can be moved via sliding only in the x and y axises (This is unused under normal gameplay)
|
||||
- 2: An ice cube that can be moved via sliding only in the z and y axises (This is unused under normal gameplay)
|
||||
- 3: An ice cube that can be moved via sliding only in the x and z axises and that can shatter and respawn if it ever collides with a gameObject having the tag `RockLimit`
|
||||
- `data[3]`: If it's 1, it is assumed to be a pushable ice cube, but allows all movement axises
|
||||
- `vectordata[0].x`: UNUSED (was used to specify the scale of the special collider mentioned in `data[0]`)
|
||||
- `vectordata[0].y`: The y velocity when Horn Slash is used for the launch when this is a rock
|
||||
@@ -22,6 +22,7 @@ A rock or a pushable ice cube that can be moved using Kabbu's Horn Slash with co
|
||||
This object is very complex and even includes unused logic under normal gameplay. The underlying system is simpler to explain in its own section which is what this section will attempt to do. If more details are needed, check the other sections.
|
||||
|
||||
There are 2 modes to this object which is determined by `data[2]`:
|
||||
|
||||
- A rock that can be launched in any directions
|
||||
- A pushable ice cube that can only be pushed using restricted axises (under normal gameplay, only the y axis is disallowed for movement which is what will be assumed here)
|
||||
|
||||
@@ -31,22 +32,26 @@ In either cases, `internalcollider[0]` is set to the collider of the entity.`mod
|
||||
When a `BeetleHorn` collides with this while it's not `trapped`, a launch occurs by setting the entity.`rigid` velocity in x/z to match the opposite relative direction of the player with the y being from `vectordata[0].y`. The force of the launch is controlled by a multiplier which is the value of `vectordata[0].z`. As part of the setup, `icevel` is set to the new entity.`rigid`.
|
||||
|
||||
During Update, the velocity is managed:
|
||||
|
||||
- If the absolute value of the entity.`rigid` y velocity is 0.1 or below (or `onground` became true when absolute y velocity is below 0.15), `icevel` is zeroed out
|
||||
- The entity.`rigid` x and z velocity are set to the `icevel` ones, but the y is kept
|
||||
|
||||
What this means is that while the y velocity is managed by Unity's physics, the x and z ones will zero out whenever the rock has reached low y velocity (which happens at halfway point of the launch) or it has touched the ground. This will eventually cause the rock to remain at rest on the ground.
|
||||
|
||||
Worth to note however: this mode has special logic:
|
||||
|
||||
- The frictions (static and dynamic) are set to 1.0 or 0.0 depending on if the y velocity is too small in either directions while entity.`onground` is true
|
||||
- A `Thud` sound occurs when the GroundDetector of the entity sees that the object collided with the ground while it was in the air before, but this can only happen if it's been more than 5.0 frames since the launch
|
||||
|
||||
### Pushable ice cube
|
||||
To keep track of this one, some internal fields are used:
|
||||
|
||||
- `internaldata[0]`: The number of frames since the last push
|
||||
- `internalvector[0]`: The direction the cube should be going (Computed by using CardinalSnap)
|
||||
- `internalvector[1]`: The last position of the ice cube since the last update cycle
|
||||
|
||||
When a `BeetleHorn` collides with this while it's not `trapped`, a push is setup:
|
||||
|
||||
- `internalvector[0]` is set to the CardinalSnap of the angle the relative to the player
|
||||
- `internaldata[0]` is set to 0.0 frames
|
||||
- `internaldata[1]` to a very high vector (999.0, 999.0, 999.0).
|
||||
@@ -55,7 +60,8 @@ This means the cube will only try to move in x OR z and to the opposite directio
|
||||
|
||||
The actual movement happens during Update where it will move by incremented the position by `internalvector[0]` * `vectordata[0].z` * framestep. Everytime this happens, `internaldata[0]` is incremented by framestep.
|
||||
|
||||
This keeps going until the ice cube cam't move in the current direction because it's being blocked by a collider or all of the following are true
|
||||
This keeps going until the ice cube cam't move in the current direction because it's being blocked by a collider or all of the following are true:
|
||||
|
||||
- The velocity ramped up for longer than 10.0 frames
|
||||
- MainManager.FrameDifference returns true (normally returns true, but can skip frames on vsync if the the refresh rate is higher than 60 htz)
|
||||
- The object moved less than half the x/z multiplier since the last update cycle
|
||||
@@ -77,9 +83,9 @@ A special case can happen if `data[3]` is 1: it allows the ice cube to move in t
|
||||
- The NPCControl's `rotater` is initialised to a new GameObject named `rotater` childed to this object with a local position of Vector3.zero.
|
||||
- If `data[1]` is 1, the entity.`rigid` have all its constraints removed (this never happens under normal gameplay).
|
||||
- If `data[2]` is present and above 0, the following happens:
|
||||
- The entity's `onground` is set to false
|
||||
- The `actioncooldown` is set to 300.0
|
||||
- If the `boxcol`.size has a magnitude above 0.1, the first child of the entity's `model` has its scale set to the `boxcol`.size and its local position to (0.0, `boxcol.size.y` / 2, 0.0). The `boxcol` size then gets zeroed out
|
||||
- The entity's `onground` is set to false
|
||||
- The `actioncooldown` is set to 300.0
|
||||
- If the `boxcol`.size has a magnitude above 0.1, the first child of the entity's `model` has its scale set to the `boxcol`.size and its local position to (0.0, `boxcol.size.y` / 2, 0.0). The `boxcol` size then gets zeroed out
|
||||
|
||||
## Update
|
||||
If `data[2]` isn't defined or it's 0, PushRockStuff is called (see the section below for details).
|
||||
@@ -88,6 +94,7 @@ Otherwise, the following section occurs.
|
||||
|
||||
### `data[2]` is above 0
|
||||
Some steps occurs depending on the value of `data[2]` (neither happens under normal gameplay):
|
||||
|
||||
- 1: The z position is set to the entity.`startpos.z`
|
||||
- 2: The x position is set to the entity.`startpos.x`
|
||||
|
||||
@@ -97,20 +104,22 @@ There are 2 subsections, they happen in order if applicable and they aren't mutu
|
||||
This sub section only happens when `hit` is true which can only happen if it was a slidable ice cube. It decides if the cube should be moving or be at rest if it has been moving.
|
||||
|
||||
`hit` is set to false and the entity.`rigid` velocity is set to Vector3.zero (which stops its movement and allows to pushed again) if any of the following conditions is true:
|
||||
|
||||
- No colliders are detected in a sphere of radius 1.5 with the center being this position + (0.0, 1.0, 0.0) + `internalvector[0]` * 2.0 other than the `ccol`, `boxcol`, `scol`, `pusher` and any colliders in `internalcollider` (Meaning the ice cube cam't move in the current direction because it's being blocked by a collider)
|
||||
- `data[2]` is between 1 and 2 (never happens under normal gameplay)
|
||||
- The entity is not `inice` and the map isn't an `icemap`
|
||||
- All of the following are true
|
||||
- `internaldata[0]` is above 10.0 (meaning the velocity ramped up for longer than 10.0 frames)
|
||||
- MainManager.FrameDifference returns true (normally returns true, but can skip frames on vsync if the the refresh rate is higher than 60 htz)
|
||||
- The distance between this object position and `internalvector[1]` is less than `vectordata[0].z` / 2.0 (meaning the object moved less than half the x/z multiplier since the last update cycle)
|
||||
- `internaldata[0]` is above 10.0 (meaning the velocity ramped up for longer than 10.0 frames)
|
||||
- MainManager.FrameDifference returns true (normally returns true, but can skip frames on vsync if the the refresh rate is higher than 60 htz)
|
||||
- The distance between this object position and `internalvector[1]` is less than `vectordata[0].z` / 2.0 (meaning the object moved less than half the x/z multiplier since the last update cycle)
|
||||
|
||||
Otherwise, the following occurs (meaning the cube should be moving):
|
||||
|
||||
- `internalvector[1]` is set to this object's position
|
||||
- The entity.`rigid` have its rotation frozen, but it is possible to get an additional axis movement constraint frozen if the entity is `onground` or `data[3]` is present and is 1 in addition to:
|
||||
- `data[2]` being 1: z movement are frozen (never happens under normal gameplay)
|
||||
- `data[2]` being 2, x movement are frozen (never happens under normal gameplay)
|
||||
- `data[2]` being 3 and `data[3]` is present and is 1, y movement are frozen
|
||||
- `data[2]` being 1: z movement are frozen (never happens under normal gameplay)
|
||||
- `data[2]` being 2, x movement are frozen (never happens under normal gameplay)
|
||||
- `data[2]` being 3 and `data[3]` is present and is 1, y movement are frozen
|
||||
- This object position is incremented by `internalvector[0]` * `vectordata[0].z` * framestep
|
||||
|
||||
Finally, `internaldata[0]` is incremented by framestep and the `actioncooldown` is set to 300.0.
|
||||
@@ -121,6 +130,7 @@ This sub section only happens when the entity isn't `inice` and the map.`icemap`
|
||||
The entity.`model` local position is set to Vector3.zero unless there's less than 100.0 frames left to the `actioncooldown` in which case, it's a random vector between (-0.1, 0.0, 0.0) to (0.1, 0.0, 0.0). This slightly shakes the model horizontally.
|
||||
|
||||
If the `actioncooldown` hasn't expired, it is decremented by framestep. Otherwise, BreakIceRock is called which does the following (Basically, this respawns the ice cube):
|
||||
|
||||
- The `IceShatter` particle is played at this object position + vector3.up with the angles (-90.0, 0.0, 0.0) for 1 second
|
||||
- The `Audio/Sounds/IceBreak` audio clip is played at this object position with the volume being proportional to the sound distance of the object to the camera scaled by the soundvolume
|
||||
- The `actioncooldown` is set to 300.0
|
||||
@@ -148,11 +158,13 @@ No friction change of the entity.`ccol` can occur with an object of this type be
|
||||
|
||||
## OnTriggerEnter
|
||||
There are 2 branches in this:
|
||||
|
||||
- Where the other gameObject tag is `RockLimit` and `data[2]` is 3
|
||||
- Where the other gameObject tag is `BeetleHorn` and we aren't `trapped`
|
||||
|
||||
### `RockLimit`
|
||||
BreakIceRock is called which does the following:
|
||||
|
||||
- The `IceShatter` particle is played at this object position + vector3.up with the angles (-90.0, 0.0, 0.0) for 1 second
|
||||
- The `Audio/Sounds/IceBreak` audio clip is played at this object position with the volume being proportional to the sound distance of the object to the camera scaled by the soundvolume
|
||||
- The `actioncooldown` is set to 300.0
|
||||
@@ -168,6 +180,7 @@ Then, HitPart particles are played at this position + (0.0, 0.5, 0.0) and the `r
|
||||
After, there are 2 kinds of logic there and it depends on `data[2]` existing and either the entity.`onground` is true or `data[3]` exists and is 1. Either starts a movement on the rock or ice cube
|
||||
|
||||
If the above is violated (This is a rock):
|
||||
|
||||
- The entity.`rigid` x and z velocity are set to be 0.0 - `rotater.forward.x` and 0.0 - `rotater.forward.z` respectively, each scaled by `vectordata[0].z`. The y velocity is set to `vectordata[0].y`
|
||||
- `icevel` is set to the entity.`rigid` velocity
|
||||
- The entity `onground` is set to false
|
||||
@@ -176,12 +189,13 @@ If the above is violated (This is a rock):
|
||||
- The entity `feet.overridecd` is set to 5.0
|
||||
|
||||
If it was fufilled (This is an ice cube):
|
||||
|
||||
- `internaldata[0]` is set to 0.0
|
||||
- `internalvector[1]` is set to (999.0, 999.0, 999.0)
|
||||
- What happens next depends on `data[2]`:
|
||||
- If it's 0, the same logic occurs than if `data[2]` didn't existed in the first place
|
||||
- If it's 1 or 2, `hit` is set to true (Never happens under normal gameplay)
|
||||
- If it's 3, `internalvector[0]` is set to the CardinalSnap of the `rotater` and `hit` is set to true
|
||||
- If it's 0, the same logic occurs than if `data[2]` didn't existed in the first place
|
||||
- If it's 1 or 2, `hit` is set to true (Never happens under normal gameplay)
|
||||
- If it's 3, `internalvector[0]` is set to the CardinalSnap of the `rotater` and `hit` is set to true
|
||||
|
||||
## GroundDetector.OnTriggerStay
|
||||
If the object reached the ground while it was in the air before and `actioncooldown` expired, DeathSmoke particles are played at the object position + the forward vector of the camera * -0.35 followed by a `Thud` sound played on the entity at 0.4 volume and 1.5 pitch.
|
||||
|
||||
@@ -6,6 +6,7 @@ None.
|
||||
|
||||
## Setup
|
||||
A few adjustements occurs:
|
||||
|
||||
- The entity.`alwaysactive` is set to true
|
||||
- The gameObject's isStatic is set to true
|
||||
- The entity.`rigid` is placed in kinematic mode without gravity
|
||||
|
||||
@@ -31,8 +31,8 @@ A rolling rock that either appears and rolls on its own or is shot from a canon.
|
||||
### When we are shooting from a canon (`data[2]` is 1)
|
||||
- `actioncooldown` is set to `vectordata[1].z`
|
||||
- `internaltransform` is initialised to have 2 transforms:
|
||||
- The first is an instance of the `Prefabs/Objects/Cannon` prefab childed to the current map with a scale of Vector3.one * (`vectordata[1].y` / 2.0), a position of the entity.`startpos` and with angles incremented by (0f, 0f, -90f).
|
||||
- The second is the first child from the root of the canon instance (the cylinder nozzle)
|
||||
- The first is an instance of the `Prefabs/Objects/Cannon` prefab childed to the current map with a scale of Vector3.one * (`vectordata[1].y` / 2.0), a position of the entity.`startpos` and with angles incremented by (0f, 0f, -90f).
|
||||
- The second is the first child from the root of the canon instance (the cylinder nozzle)
|
||||
- The canon is set to rotate its y angle (not its x and z) to face the canon's current position + `vectordata[0]`. This aligns it horizontally to its target
|
||||
- The entity.`rigid` is locked via [LockRigid(true)](../../EntityControl/EntityControl%20Methods.md#lockrigid)
|
||||
- The position of the the rolling rock is set to (0.0, 999.0, 0.0) which is offscreen in the air
|
||||
@@ -46,6 +46,7 @@ This section involves 2 countdown timer: `internaldata[0]` and `actioncooldown`.
|
||||
On the first update, `internaldata[0]` is expired, but not `actioncooldown` which will cause this object to be continuously positioned offscreen (0.0, 999.0, 0.0). If this happens while the `data[3]` `hit` check condition is fufilled or not applicable, this is where the `actioncooldown` is decremented by the game's frametime. On top of this, if less than 60.0 frames is left on the `actioncooldown`, the local scale of the nozzle is set to a lerp from the existing one to (0.5, 1.25, 1.25) with a factor of the 1/20 of the game's frametime. This scale signals that the canon is about to shoot by warping it mostly from the side for a brief moment.
|
||||
|
||||
Eventually, the `actioncooldown` expires and this is detected by going below 0.0, but remaining above -1000.0. When this happens:
|
||||
|
||||
- The entity.`rigid` gets its velocity zeroed out
|
||||
- This object's position is set to the entity.`startpos` + the normalized version of `vectordata[0]` * `vectordata[1].y` + Vector3.up * 0.25 (this places the rock back to its original position)
|
||||
- [LockRigid(false)](../../EntityControl/EntityControl%20Methods.md#LockRigid) is called on the entity to unlock its `rigid`
|
||||
@@ -58,6 +59,7 @@ As a result of this, `actioncooldown` is frozen below -1000.0, but this causes o
|
||||
From there `internaldata[0]` hasn't expired which causes further updates to decrement it by the game's frametime. Eventually, it will expire which means we are back to where we started on the first update and the cycle repeats itself.
|
||||
|
||||
Overall, it means that:
|
||||
|
||||
- Every time `actioncooldown` has 60.0 or less left, the scale of the nozzle is warped to be a bit smaller horizontally
|
||||
- When `actioncooldown` expires, the shooting logic happens with a position set and a scale of the nozzle set to be larger horizontally
|
||||
- The nozzle scale slowly gets back to normal
|
||||
@@ -67,6 +69,7 @@ This repeates over and over until the `data[3]` check is violated which freezes
|
||||
|
||||
### Main logic
|
||||
After the section above if applicable, a check is done if the rock should have its `hit` set to true. It is set to true if any of the following conditions is true:
|
||||
|
||||
- We aren't shooting from a canon and `data[0]` is 0 or the entity is `onground`
|
||||
- We are shooting from a canon and `actioncooldown` expired.
|
||||
|
||||
@@ -76,6 +79,7 @@ If we are setting `hit` to true, a special case happens when if it was false bef
|
||||
From there, what happens depends on the value of `hit`.
|
||||
|
||||
If it is true:
|
||||
|
||||
- The x and z components of the entity.`rigid` velocity are set to `vectordata[0].x` and `vectordata[0].z` respectively
|
||||
- The entity.`model` angles are incremented by `vectordata[2]` * framestep
|
||||
- If `data[3]` is present and the NPCControl at the map entity id of its value has its `hit` set to true, then [PlaySound](../../EntityControl/EntityControl%20Methods.md#PlaySound) is called with the `RollingRock` clip looped. If `data[3]` is present, but the `hit` check is violated, the entity.`sound` is stopped. NOTE: see the note on the data arrays section above for a caveat with this
|
||||
@@ -90,7 +94,7 @@ This does nothing if we are in a `pause`, `minipause` or `inevent` and that if a
|
||||
|
||||
If the other gameObject is the player and it's not `digging`, the [event](../../../Enums%20and%20IDs/Events.md) 116 (Getting crushed by a `RollingRock`) is called with this as the caller.
|
||||
|
||||
Otherwise, if the other gameObject tag is `RockLimit`, [BreakRock](../BreakRock.md) is called.
|
||||
Otherwise, if the other gameObject tag is `RockLimit`, BreakRock is called.
|
||||
|
||||
## OnCollisionEnter
|
||||
If the other gameObject is an [Object](../Object.md) NPCControl of type [BreakableRock](BreakableRock.md), [BreakRock](BreakableRock.md#breakrock) is called on the other's NPCControl.
|
||||
@@ -105,9 +109,9 @@ This is a public method that has logic specific to this object type.
|
||||
- entity.`rigid` has its velocity zeroed out
|
||||
- entity.`onground` is set to false
|
||||
- If `data[2]` is 1 (we are shooting from a canon) the following occurs (if not, WarpRock is called instead, see the section below for details):
|
||||
- The rolling rock position is offscreen in the air at (0.0, 999.0, 0.0)
|
||||
- The entity.`rigid` is locked via [LockRigid(true)](../../EntityControl/EntityControl%20Methods.md#lockrigid)
|
||||
- `actioncooldown` is reset to `vectordata[1].z`
|
||||
- The rolling rock position is offscreen in the air at (0.0, 999.0, 0.0)
|
||||
- The entity.`rigid` is locked via [LockRigid(true)](../../EntityControl/EntityControl%20Methods.md#lockrigid)
|
||||
- `actioncooldown` is reset to `vectordata[1].z`
|
||||
|
||||
## WarpRock
|
||||
This is a private method specific to this object type that prepares to respawn the rock.
|
||||
@@ -115,6 +119,7 @@ This is a private method specific to this object type that prepares to respawn t
|
||||
If we are shooting from a canon (`data[2]` is 1), [LockRigid(true)](../../EntityControl/EntityControl%20Methods.md#LockRigid) is called on the entity and the `actioncooldown` is reset to `vectordata[1].z`.
|
||||
|
||||
If we aren't shooting from a canon:
|
||||
|
||||
- This object's transform is set to (0.0, 999.0, 0.0) which is offscreen in the air
|
||||
- LatePos is called which sets the position of the entity to its `startpos` in `vectordata[1].z` seconds.
|
||||
- `hit` is set to false
|
||||
|
||||
@@ -23,10 +23,10 @@ The same than [PathPlatform](PathPlatform.md), but path mode will have the nodes
|
||||
- entity.`alwaysactive` is set to true
|
||||
- entity.`model` tag is set to `PlatformNoClock`
|
||||
- If entity.`originalid` is the `ElectroPlatform` [AnimID](../../../Enums%20and%20IDs/AnimIDs.md), a GlowTrigger is added on the first child of the `model`:
|
||||
- `getactivecolorfromstart` is set to true
|
||||
- `parent` is set to this NPCControl
|
||||
- `glowparts` is initialised to a single element corresponding to the MeshRenderer of the first child of the `model`
|
||||
- `electime` is initialised to 260.0 unless `dialogues[2].y` exists and isn't 0 where it will take that value instead
|
||||
- `getactivecolorfromstart` is set to true
|
||||
- `parent` is set to this NPCControl
|
||||
- `glowparts` is initialised to a single element corresponding to the MeshRenderer of the first child of the `model`
|
||||
- `electime` is initialised to 260.0 unless `dialogues[2].y` exists and isn't 0 where it will take that value instead
|
||||
|
||||
## Update
|
||||
If the [AnimId](../../../Enums%20and%20IDs/AnimIDs.md) is a `Lilypad`, the `boxcol` if present is kept enabled, otherwise, its enabled will bet set to the `hit` value.
|
||||
|
||||
@@ -22,6 +22,7 @@ A save crystal that can be hit using field abilities. It can be blue which only
|
||||
`internaltransform` is initialised to be 2 elements and the first one is set as the entity.`model`'s second child (the crystal GameObject) and the second is left default for now.
|
||||
|
||||
If `data[0]` is 1, the PolySphere is setup from a `Prefabs/Objects/PolySphere` prefab:
|
||||
|
||||
- childed to to `internaltransform[0]`
|
||||
- local position of (0.0, 0.0, 0.01)
|
||||
- Local scale of (8.0, 8.0, 5.0)
|
||||
@@ -37,6 +38,7 @@ The only thing that occurs here is the `internaltransform[0]` (the crystal game
|
||||
|
||||
## OnTriggerEnter
|
||||
This does nothing when any of the following are true:
|
||||
|
||||
- We are in a `pause` or `minipause`
|
||||
- The [message](../../../SetText/Notable%20states.md#message) lock is grabbed
|
||||
- The other gameObject tag isn't `BeetleHorn`, `BeetleDash` or `Icecle` while it's also not the player `beemerang`
|
||||
@@ -53,4 +55,4 @@ If the other gameObject is the player.`beemerang`, its `hit` is set to true.
|
||||
|
||||
If `data[1]` is 10 or above and `hit` is false, the game will find a DeadLanderOmega whose `thisid` is `data[1]` - 10 and call ForceLook on it using `vectordata[0]` as the vector. After, `hit` is set to true making it a one time event.
|
||||
|
||||
Otherwise, if we aren't in a `timeddemo` (we never are under normal gameplay) and the square distance between this and the player is 30.0 or less, [Interact("save")](../Interact.md) is called.
|
||||
Otherwise, if we aren't in a `timeddemo` (we never are under normal gameplay) and the square distance between this and the player is 30.0 or less, [Interact("save")](../Notable%20methods/Interact.md) is called.
|
||||
|
||||
@@ -16,8 +16,8 @@ A crank switch actuated by Vi's Beemerang Toss with an analog actuation that nee
|
||||
- `nointeract` is set to true
|
||||
- if the `activationflag` [flags](../../../Flags%20arrays/flags.md) slot is true, `hit` is also set to true.
|
||||
- From there some adjustements happens based on the `originalid`'s [AnimID](../../../Enums%20and%20IDs/AnimIDs.md)(nothing happens if it doesn't match any of them):
|
||||
- `SwitchCrystal` and `BigCrystalSwitch`: A GlowTrigger is added to the entity.`model`'s first child with its `parent` set to this object and the `glowparts` set to a single element corresponding to the MeshRender already attached to the first entity.`model` child.
|
||||
- `WoodenSwitch` and `SteelSwitch`: `internaldata` is initialised to a single element being -60 if it's a `WoodenSwitch` or -100 if it's a `SteelSwitch`, Then, the `moveobj` is set to the entity.`model` first child and if `hit` was set to true earlier, its angles are set to (0.0, `internaldata[0]`, 0.0)
|
||||
- `SwitchCrystal` and `BigCrystalSwitch`: A GlowTrigger is added to the entity.`model`'s first child with its `parent` set to this object and the `glowparts` set to a single element corresponding to the MeshRender already attached to the first entity.`model` child.
|
||||
- `WoodenSwitch` and `SteelSwitch`: `internaldata` is initialised to a single element being -60 if it's a `WoodenSwitch` or -100 if it's a `SteelSwitch`, Then, the `moveobj` is set to the entity.`model` first child and if `hit` was set to true earlier, its angles are set to (0.0, `internaldata[0]`, 0.0)
|
||||
- If the player is present, all collision between the `boxcol` and the player's wall detector are ignored.
|
||||
- If the `originalid` is not among `BigCrystalSwitch`, `WoodenSwitch` or `SteelSwitch`, [AddPushder](../Notable%20methods/AddPusher.md) is called.
|
||||
|
||||
|
||||
@@ -12,12 +12,14 @@ There are 2 modes this object can operate on:
|
||||
In the case of NPCControl management, the `boxcol`'s layer is set to 0 (default) which ends this object's setup.
|
||||
|
||||
In the case of independant management by recreating `boxcol` a new GameObject named `Respawner` with a new trigger BoxCollider that is childed to the map with the following properties:
|
||||
|
||||
- position is set to the entity.`startpos`
|
||||
- angles is set to this transform's angles
|
||||
- tag is set to `Respawn` (which allows it to be detected by PlayerControl and others)
|
||||
- isStatic is set to true
|
||||
|
||||
Finally, the gameObject gets destroyed. From now on, this NPCControl cease to exist because the entire logic is managed by an independant GameObject. The tag gives it special behaviors:
|
||||
|
||||
- The [Beemerang](Beemerang.md) entity.`ccol` and `scol` have their collisions ignored with the collider
|
||||
- OnTriggerStay of PlayerControl: if the other collider has the tag with a `vectordata[0]` above 0.1, `lastpos` is set to it.
|
||||
- OnTriggerExit of PlayerControl: `respawncount` is set to 0.0 which resets a failsafe to prevent too much infinite respawns.
|
||||
|
||||
@@ -19,8 +19,8 @@ A switch that, when activated, causes a frozen area range to appear or to disapp
|
||||
- `nointeract` is set to true
|
||||
- if the `activationflag` [flags](../../../Flags%20arrays/flags.md) slot is true, `hit` is also set to true.
|
||||
- From there some adjustements happens based on the `originalid`'s [AnimID](../../../Enums%20and%20IDs/AnimIDs.md)(nothing happens if it doesn't match any of them):
|
||||
- `SwitchCrystal` and `BigCrystalSwitch`: A GlowTrigger is added to the entity's `model`'s first child with its `parent` set to this object and the `glowparts` set to a single element corresponding to the MeshRender already attached to the first `model` child.
|
||||
- `WoodenSwitch` and `SteelSwitch`: `internaldata` is initialised to a single element being -60 if it's a `WoodenSwitch` or -100 if it's a `SteelSwitch`, Then, the `moveobj` is set to the entity's `model` first child and if `hit` was set to true earlier, its angles are set to (0.0, `internaldata[0]`, 0.0)
|
||||
- `SwitchCrystal` and `BigCrystalSwitch`: A GlowTrigger is added to the entity's `model`'s first child with its `parent` set to this object and the `glowparts` set to a single element corresponding to the MeshRender already attached to the first `model` child.
|
||||
- `WoodenSwitch` and `SteelSwitch`: `internaldata` is initialised to a single element being -60 if it's a `WoodenSwitch` or -100 if it's a `SteelSwitch`, Then, the `moveobj` is set to the entity's `model` first child and if `hit` was set to true earlier, its angles are set to (0.0, `internaldata[0]`, 0.0)
|
||||
- If the player is present, all collision between the `boxcol` and the player's wall detector are ignored.
|
||||
- If the `originalid` is not among `BigCrystalSwitch`, `WoodenSwitch` or `SteelSwitch`, [AddPushder](../Notable%20methods/AddPusher.md) is called.
|
||||
|
||||
@@ -33,9 +33,9 @@ If the entity is allowed to exist according to its `limit`, `requires` and `regi
|
||||
- `hit` is set to true if `data[1]` is 1.
|
||||
- All collisions between the `boxcol` and the SphereCollider addeed on the `internaltransform[0]` are ignored.
|
||||
- If `data[1]` isn't negative, the map entity whose id is this value is resolved and the following occurs:
|
||||
- This stencil switch gets childed to the resolved entity.`model` if it's present or the entity itself if it's not
|
||||
- This stencil switch position is set to the resolved entity position + `vectordata[1]`
|
||||
- This stencil switch entity.`startpos` is set to its position
|
||||
- This stencil switch gets childed to the resolved entity.`model` if it's present or the entity itself if it's not
|
||||
- This stencil switch position is set to the resolved entity position + `vectordata[1]`
|
||||
- This stencil switch entity.`startpos` is set to its position
|
||||
- If `data[3]` is 1 and the entity has a `model`, the collider on that `model` if it exist gets disabled and DisableAllColliders is invoked in 0.1 seconds which disables the entity.`ccol`, the `scol`, the `boxcol` and the `pusher` if any were present
|
||||
- `internaltransform[0]` gets childed to the map and its position is set to this stencil switch position
|
||||
|
||||
@@ -50,6 +50,7 @@ If `data[1]` isn't negative (another map entity is the parent of this stencil sw
|
||||
This method specifically targets any NPCControl of this object type. It is called for any MapControl LateUpdate after the first one.
|
||||
|
||||
If any exists in the map where their entity isn't `iskill` and their `hit` value is true, it will select the first one. With it, 2 shaders global properties are set:
|
||||
|
||||
- `GlobalIceRadius`: Half of the magnitude of the `internfaltransform[0]` (the ice radius object) scale
|
||||
- `CentralIcePoint`: the sencil switch position
|
||||
|
||||
@@ -59,12 +60,14 @@ If no actuated stencil switches are found, the `stencilid` remains at -1 and the
|
||||
|
||||
## OnTriggerEnter
|
||||
Nothing happens if any of the following is true:
|
||||
|
||||
- We are in a `pause` or `minipause`
|
||||
- [message](../../../SetText/Notable%20states.md#message) is grabbed
|
||||
- `collisionammount` is higher than 1 (this is a debounce protection)
|
||||
- The other gameObject tag isn't `BeetleHorn`, `BeetleDash`, `Icefall` and `Icecle` while it's not the player `beemerang`
|
||||
|
||||
The following occurs if we the above is fufilled:
|
||||
|
||||
- `collisionammount` is incremented
|
||||
- A HitPart particle is played at this position + (0.0, 0.5, 0.0)
|
||||
- All collisions between the entity.`ccol` and the SphereCollider of `internaltransform[0]` (the ice radius) are ignored
|
||||
@@ -74,7 +77,7 @@ The following occurs if we the above is fufilled:
|
||||
- If `hit` is true, the corresponding [regionalflag](../../../Flags%20arrays/Regionalflags.md) slot of `regionalflag` when it isn't negative is set to true the corresponding [flag](../../../Flags%20arrays/flags.md) slot of `activationflag` when it isn't negative is set to true
|
||||
- DeactivateOtherStencil is called which deactivates all other `StencilSwitch` in the current map whose entity aren't `iskill` by having their `hit` set to false
|
||||
- If the other gameObject was the player `beemerang`, its `hit` is set to true and the `WoodHit` sound is played on the entity
|
||||
- If the entity `originalid` isn't -1 (`None`), [SwitchSound](../SwitchSound.md) is called indicating a press
|
||||
- If the entity `originalid` isn't -1 (`None`), [SwitchSound](../Notable%20methods/SwitchSound.md#switchsound) is called indicating a press
|
||||
|
||||
## EntityControl.OnTriggerStay
|
||||
Due to the `IceRadius` tag of the ice radius object, any entities that collides with it has their `inice` set to true which update thier sprites and animation accordingly.
|
||||
@@ -41,8 +41,8 @@ Unless stated otheriwse, `activationflag` and `regionalflag` only applies when t
|
||||
- `nointeract` is set to true
|
||||
- if the `activationflag` [flags](../../../Flags%20arrays/flags.md) slot is true, `hit` is also set to true.
|
||||
- From there some adjustements happens based on the `originalid`'s [AnimID](../../../Enums%20and%20IDs/AnimIDs.md)(nothing happens if it doesn't match any of them):
|
||||
- `SwitchCrystal` and `BigCrystalSwitch`: A GlowTrigger is added to the entity.`model`'s first child with its `parent` set to this object and the `glowparts` set to a single element corresponding to the MeshRender already attached to the first `model` child.
|
||||
- `WoodenSwitch` and `SteelSwitch`: `internaldata` is initialised to a single element being -60 if it's a `WoodenSwitch` or -100 if it's a `SteelSwitch`, Then, the `moveobj` is set to the entity's `model` first child and if `hit` was set to true earlier, its angles are set to (0.0, `internaldata[0]`, 0.0)
|
||||
- `SwitchCrystal` and `BigCrystalSwitch`: A GlowTrigger is added to the entity.`model`'s first child with its `parent` set to this object and the `glowparts` set to a single element corresponding to the MeshRender already attached to the first `model` child.
|
||||
- `WoodenSwitch` and `SteelSwitch`: `internaldata` is initialised to a single element being -60 if it's a `WoodenSwitch` or -100 if it's a `SteelSwitch`, Then, the `moveobj` is set to the entity's `model` first child and if `hit` was set to true earlier, its angles are set to (0.0, `internaldata[0]`, 0.0)
|
||||
- If the player is present, all collision between the `boxcol` and the player's wall detector are ignored.
|
||||
- If the `originalid` is not among `BigCrystalSwitch`, `WoodenSwitch` or `SteelSwitch`, [AddPushder](../Notable%20methods/AddPusher.md) is called.
|
||||
- If `data[4]` is 1 the entity's `rotater` tag gets set to `Hornable` (allows PlayerControl to get a green ! emoticon when getting 2.5 or lower distance from the switch for 5 frames).
|
||||
@@ -51,6 +51,7 @@ Unless stated otheriwse, `activationflag` and `regionalflag` only applies when t
|
||||
What happens at the start depends on `data[1]` and `data[2]`.
|
||||
|
||||
If `data[1]` is 0 and `data[2]` is present and not negative:
|
||||
|
||||
- If the `actioncooldown` hasn't expired, it is decremented by the game's frametime. Otherwise, if the `actioncooldown` expired on the last update cycle (checked by being above -1000.0), `hit` is set to false and `actioncooldown` is set to -1100.0 so it doesn't perform this logic on further updates (this is the autooff feature taking effect)
|
||||
- If the `activationflag` isn't negative and the [flag](../../../Flags%20arrays/flags.md) slot of it is true, `hit` is set to true.
|
||||
|
||||
@@ -60,6 +61,7 @@ In all cases, if the entity.`originalid` is the `WoodenSwitch` or `SteelSwitch`
|
||||
|
||||
## OnTriggerEnter
|
||||
Nothing happens if any of the following is true:
|
||||
|
||||
- We are in a `pause` or `minipause`
|
||||
- [message](../../../SetText/Notable%20states.md#message) is grabbed
|
||||
- `collisionammount` is higher than 1 (this is a debounce protection)
|
||||
@@ -67,16 +69,18 @@ Nothing happens if any of the following is true:
|
||||
- `data[4]` is not present or it is and its value is 1 while the other gameObject tag is `BeetleHorn` or `BeetleDash` (This basically enforces that `data[4]` being 1 means that only Kabbu's horn can actuate the switch)
|
||||
|
||||
The following occurs:
|
||||
|
||||
- `collisionammount` is incremented
|
||||
- A HitPart particle is played at this position + (0.0, 0.5, 0.0)
|
||||
- The main logic section occurs, see below for details
|
||||
- If the other gameObject was the player `beemerang`, its `hit` is set to true and the `WoodHit` sound is played on the entity
|
||||
- If the entity `originalid` isn't -1 (`None`), [SwitchSound](../SwitchSound.md) is called indicating a press
|
||||
- If the entity `originalid` isn't -1 (`None`), [SwitchSound](../Notable%20methods/SwitchSound.md#switchsound) is called indicating a press
|
||||
|
||||
What happens in the main logic depends on `data[0]`.
|
||||
|
||||
### `data[0]` is 1
|
||||
This does nothing if `hit` is true and the `TOG` [modifier](../../EntityControl/Modifiers.md) is not active:
|
||||
|
||||
- If `data[1]` isn't negative, the [event](../../../Enums%20and%20IDs/Events.md) at its id is started which this being the caller. Otherwise, the [regionalflag](../../../Flags%20arrays/Regionalflags.md) slot at `regionalflags` and the [flag](../../../Flags%20arrays/flags.md) slot at `activationflag` are set to true
|
||||
- `hit` is set to true unless the `TOG` [modifier](../../EntityControl/Modifiers.md) is active in which case, the value is toggled instead
|
||||
- If the entity `originalid` is -1 (`None`), its `iskill` is set to true
|
||||
@@ -84,6 +88,7 @@ This does nothing if `hit` is true and the `TOG` [modifier](../../EntityControl/
|
||||
|
||||
### `data[0]` is 0
|
||||
This depends on `data[1]`. If it's not 1, then `hit` is set to true and the [regionalflag](../../../Flags%20arrays/Regionalflags.md) slot at `regionalflags` and the [flag](../../../Flags%20arrays/flags.md) slot at `activationflag` are set to true. If it's 1 and the `actioncooldown` expired:
|
||||
|
||||
- `hit` is toggled
|
||||
- `actioncooldown` is set to 30.0
|
||||
- If the `activationflag` isn't negative, the corresponding [flag](../../../Flags%20arrays/flags.md) slot is set to `hit`
|
||||
|
||||
@@ -10,6 +10,7 @@ A platform that can only be stood on by the player for a limited amount of time
|
||||
|
||||
## Setup
|
||||
A few adjustements occurs:
|
||||
|
||||
- The entity.`alwaysactive` is set to true
|
||||
- The gameObject's isStatic is set to true
|
||||
- The entity.`rigid` is placed in kinematic mode without gravity
|
||||
@@ -24,10 +25,12 @@ The player.entity.`forceclosemove` is set to `hit` (whether or not the player is
|
||||
What happens after depends on the `hit` value
|
||||
|
||||
If it is true:
|
||||
|
||||
- If the `actioncooldown` hasn't expired yet, it is decremented by the game's frametime and if `data[3]` is 0, the entity.`model` local position is set to (Random.Range(-0.05, 0.05), 0.0, 0.0) (this makes it shake horizontally)
|
||||
- If the `actioncooldown` expired on the last update cycle (checked by being above -99999.0), it is set to -100000.0 and if `data[1]` and `data[2]` are both 1, the RespawnPlayer coroutine is started (see its section section for details).
|
||||
|
||||
If it is false:
|
||||
|
||||
- `actioncooldown` is set to `data[0]`
|
||||
- The entity.`model` local position is set to Vector3.zero
|
||||
|
||||
@@ -55,6 +58,7 @@ Finally, a fade in from black is done with a speed of 0.1 and all playerdata ent
|
||||
|
||||
## OnTriggerEnter
|
||||
If the other collider is the player.entity.`feet` (its ground detector) then 2 things occurs:
|
||||
|
||||
- If `data[3]` is 1, the `Shaking` animation clip will play on the entity.`anim` when the player.entity.`feet` (the ground detector) collides with the platform. This is a [non standard animation](../../EntityControl/Animations/animstate.md#non-standard-animations)
|
||||
- `hit` is set to true
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@ A trigger zone that controls either its own `hit` value when the player enters o
|
||||
## Data Arrays
|
||||
- `data[0]`: If it's -1, the trigger manages its own `hit` value when the player enters or exits the zone. If it's 0 or above, it manages the `hit` value of the map entity whose id is that value when the player enters the zone (not when they exit it). NOTE: any values below -1 are considered invalid because while this trigger `hit` will be set when the player enters the zone, it will not be set when the player exits the zone
|
||||
- `data[1]`: This has 3 possible valid values (any other values is invalid and causes illogical behaviors):
|
||||
- -1: the `hit` value of the refered entity will be toggled when entered. If `data[0]` is -1 on top of this, the `hit` value will always be set to false when the player exits the zone
|
||||
- 0: the `hit` value of the refered entity will be set to false when the player enters the zone. If `data[0]` is -1, it will be set to true when the player exits the zone
|
||||
- 1: the `hit` value of the refered entity will be set to true when the player enters the zone. If `data[0]` is -1, it will be set to false when the player exits the zone
|
||||
- -1: the `hit` value of the refered entity will be toggled when entered. If `data[0]` is -1 on top of this, the `hit` value will always be set to false when the player exits the zone
|
||||
- 0: the `hit` value of the refered entity will be set to false when the player enters the zone. If `data[0]` is -1, it will be set to true when the player exits the zone
|
||||
- 1: the `hit` value of the refered entity will be set to true when the player enters the zone. If `data[0]` is -1, it will be set to false when the player exits the zone
|
||||
- `data[2]`: If it's 1, the player.`beemerang` is destroyed when entering the zone
|
||||
|
||||
## Additional data
|
||||
@@ -15,6 +15,7 @@ A trigger zone that controls either its own `hit` value when the player enters o
|
||||
|
||||
## Setup
|
||||
A few adjustements occurs:
|
||||
|
||||
- The entity.`alwaysactive` is set to true
|
||||
- The gameObject's isStatic is set to true
|
||||
- The entity.`rigid` is placed in kinematic mode without gravity
|
||||
@@ -27,6 +28,7 @@ If the `timer` hasn't expired yet, it is decremented by the game's frametime cla
|
||||
|
||||
## OnTriggerStay
|
||||
This does nothing if any of the following is true:
|
||||
|
||||
- The player isn't present
|
||||
- The other gameObject isn't the player
|
||||
- We are `inevent`
|
||||
|
||||
@@ -17,17 +17,17 @@ A switch with 2 states to control the vertical position of a child of the map's
|
||||
- `nointeract` is set to true
|
||||
- if the `activationflag` [flags](../../../Flags%20arrays/flags.md) slot is true, `hit` is also set to true.
|
||||
- From there some adjustements happens based on the `originalid`'s [AnimID](../../../Enums%20and%20IDs/AnimIDs.md)(nothing happens if it doesn't match any of them):
|
||||
- `SwitchCrystal` and `BigCrystalSwitch`: A GlowTrigger is added to the entity's `model`'s first child with its `parent` set to this object and the `glowparts` set to a single element corresponding to the MeshRender already attached to the first `model` child.
|
||||
- `WoodenSwitch` and `SteelSwitch`: `internaldata` is initialised to a single element being -60 if it's a `WoodenSwitch` or -100 if it's a `SteelSwitch`, Then, the `moveobj` is set to the entity's `model` first child and if `hit` was set to true earlier, its angles are set to (0.0, `internaldata[0]`, 0.0)
|
||||
- `SwitchCrystal` and `BigCrystalSwitch`: A GlowTrigger is added to the entity's `model`'s first child with its `parent` set to this object and the `glowparts` set to a single element corresponding to the MeshRender already attached to the first `model` child.
|
||||
- `WoodenSwitch` and `SteelSwitch`: `internaldata` is initialised to a single element being -60 if it's a `WoodenSwitch` or -100 if it's a `SteelSwitch`, Then, the `moveobj` is set to the entity's `model` first child and if `hit` was set to true earlier, its angles are set to (0.0, `internaldata[0]`, 0.0)
|
||||
- If the player is present, all collision between the `boxcol` and the player's wall detector are ignored.
|
||||
- If the `originalid` is not among `BigCrystalSwitch`, `WoodenSwitch` or `SteelSwitch`, [AddPushder](../Notable%20methods/AddPusher.md) is called.
|
||||
- `internaltransform` is initialised to a single element being the child of the map's main object at index `data[0]` which is the object that will be moved vertically.
|
||||
- `data[0]` is then overriden to `vectordata[0].x` (the amount of frames to wait between full y position changes)
|
||||
- `vectordata` is completely overriden to a new array of 4 elements:
|
||||
- 0: The loaded `vectordata[0]` before this override
|
||||
- 1: The absolute position of `internaltransform[0]`, but the y component is the loaded `vectordata[0].z` (the lower position to have the object move towards)
|
||||
- 2: The absolute position of `internaltransform[0]`, but the y component is the loaded `vectordata[0].y` (the higher position to have the object move towards)
|
||||
- 3: (The loaded `vectordata[0].x` before this override, 0.0, 0.0)
|
||||
- 0: The loaded `vectordata[0]` before this override
|
||||
- 1: The absolute position of `internaltransform[0]`, but the y component is the loaded `vectordata[0].z` (the lower position to have the object move towards)
|
||||
- 2: The absolute position of `internaltransform[0]`, but the y component is the loaded `vectordata[0].y` (the higher position to have the object move towards)
|
||||
- 3: (The loaded `vectordata[0].x` before this override, 0.0, 0.0)
|
||||
- `internaltransform[0]`'s isStatic is set to false
|
||||
- If `hit` is true, `vectordata[0].x` is set to the loaded value (which will have the object move to its upper bound position). Otherwise, `vectordata[0]` is set to Vector3.zero (which will have the object move to its lower bound position).
|
||||
- The y component of the position of `internaltransform[0]` is set to the loaded `vectordata[0].y` if `hit` is true or to the loaded `vectordata[0].z` if it's false. This sets the starting y position according to the switch `hit` value.
|
||||
@@ -39,6 +39,7 @@ After, this is where `vectordata[0].x` is incremented or decremented by the game
|
||||
|
||||
## OnTriggerEnter
|
||||
Nothing happens if any of the following is true:
|
||||
|
||||
- We are in a `pause` or `minipause`
|
||||
- [message](../../../SetText/Notable%20states.md#message) is grabbed
|
||||
- `collisionammount` is higher than 1 (this is a debounce protection)
|
||||
@@ -46,6 +47,7 @@ Nothing happens if any of the following is true:
|
||||
- `data[4]` is not present or it is and its value is 1 while the other gameObject tag is `BeetleHorn` or `BeetleDash` (This basically enforces that `data[4]` being 1 means that only Kabbu's horn can actuate the switch)
|
||||
|
||||
The following occurs if we the above is fufilled:
|
||||
|
||||
- `collisionammount` is incremented
|
||||
- A HitPart particle is played at this position + (0.0, 0.5, 0.0)
|
||||
- `hit` gets toggled
|
||||
@@ -53,4 +55,4 @@ The following occurs if we the above is fufilled:
|
||||
- If `activationflag` isn't negative, the corresponding [flag](../../../Flags%20arrays/flags.md) slot is set to `hit`
|
||||
- `actioncooldown` is then set to 30.0
|
||||
- If the other gameObject was the player `beemerang`, its `hit` is set to true and the `WoodHit` sound is played on the entity
|
||||
- If the entity `originalid` isn't -1 (`None`), [SwitchSound](../SwitchSound.md) is called indicating a press
|
||||
- If the entity `originalid` isn't -1 (`None`), [SwitchSound](../Notable%20methods/SwitchSound.md#switchsound) is called indicating a press
|
||||
@@ -21,12 +21,13 @@ The method then determines if we should operate the windpusher vertically or hor
|
||||
The wind pusher y angle (not the x and z ones) is then set to face `vectordata[0]` which alignes the wind pusher horizontally with its wind end position (no vertical alignement is needed because the `boxcol` will be adjusted accordinginly and the wind particles gets their own rotation when operating vertically).
|
||||
|
||||
The `boxcol` is created by adding a fresh trigger one. This implies that all fields pertaining to the `boxcol` when loading the entity data are overriden and they are not honored. The `boxcol` size and center depends on whether we operate horizontall or vertically:
|
||||
|
||||
- horizontally:
|
||||
- size of (`vectordata[1].y`, `vectordata[1].z`, distance between the root transform and `vectordata[0]`)
|
||||
- center of (0.0, 0.0, hald of the distance between the root transform and `vectordata[0]`)
|
||||
- size of (`vectordata[1].y`, `vectordata[1].z`, distance between the root transform and `vectordata[0]`)
|
||||
- center of (0.0, 0.0, hald of the distance between the root transform and `vectordata[0]`)
|
||||
- vertically:
|
||||
- size of (`vectordata[1].y`, distance between the root transform and `vectordata[0]`, `vectordata[1].z`)
|
||||
- center of (0.0, hald of the distance between the root transform and `vectordata[0]`, 0.0)
|
||||
- size of (`vectordata[1].y`, distance between the root transform and `vectordata[0]`, `vectordata[1].z`)
|
||||
- center of (0.0, hald of the distance between the root transform and `vectordata[0]`, 0.0)
|
||||
|
||||
`internalvector` is initialised to a single element containing the up vector of the transform if operated vertically or the forward one if operated horizontally. This is supposed to indicate the normalised wind flow direction.
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# Setup
|
||||
This method is only called during [Start](Start.md) and it contains most of the logic of the startup process. The logic depends on the [NPCType](NPCType.md), [ObjectTypes](ObjectTypes.md), [ActionBehaviors](ActionBehaviors.md) and [Interaction](Interaction.md). Consult each's documentation to learn more as only the end part of the method is shared.
|
||||
This method is only called during [Start](Start.md) and it contains most of the logic of the startup process. The logic depends on the [NPCType](NPCType.md), [ObjectTypes](Object.md#objecttypes), [ActionBehaviors](ActionBehaviors.md) and [Interaction](Interaction.md). Consult each's documentation to learn more as only the end part of the method is shared.
|
||||
|
||||
## Common startup
|
||||
At the end of the method, this phase happens regardless of the logic performed prior.
|
||||
|
||||
CheckHidden is invoked in 1 second which setups the logic to check if the NPCControl should be considered a hidden item. This happens if [HasHiddenItem](HasHiddenItem.md) returns true and CheckIfCanExist returns false according to the `requires`, `limit` and `regional`. This will cause the Detector [medal](../../Enums%20and%20IDs/Medal.md) to beep and the correct emoticon (id 4) to be set on the player entity for 100.0 frames, but this part is done by MapControl's LateUpdate.
|
||||
CheckHidden is invoked in 1 second which setups the logic to check if the NPCControl should be considered a hidden item. This happens if [HasHiddenItem](Notable%20methods/HasHiddenItem.md) returns true and CheckIfCanExist returns false according to the `requires`, `limit` and `regional`. This will cause the Detector [medal](../../Enums%20and%20IDs/Medal.md) to beep and the correct emoticon (id 4) to be set on the player entity for 100.0 frames, but this part is done by MapControl's LateUpdate.
|
||||
|
||||
After, the entity.`rigid` gets frozen on all constraints if the entity.`fixedentity` or `freezeconstraints` is true.
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
The way the game defines a shop is complex and it involves a unique way to load its data and to create the actual shop at loading time. This results in multiple NPCControl being involved at runtime that forms the logic of the shop.
|
||||
|
||||
There are 2 types of shops:
|
||||
|
||||
- A standard [items](../../Enums%20and%20IDs/Items.md) shop (key items aren't supported, see how `dialogues[10].x` works below for details)
|
||||
- A [medals](../../Enums%20and%20IDs/Medal.md) shop
|
||||
|
||||
@@ -14,7 +15,7 @@ This page will describe the loading time behaviors as the runtime will be descri
|
||||
## SemiNPC
|
||||
This [NPCType](NPCType.md) is very special in the shop system because it is the game's only usage of them (there is no map entity data that loads it as it is considered invalid since the shop system created them when needed). Its functioning is essential for the shop system, enough to document it in this page.
|
||||
|
||||
The basic idea of a SemiNPC is it behaves mostly like an [Object](NPCType.md#object), but it allows interactions. This is ideal for a shelved item because it's possible to leave the [objecttype](ObjectTypes.md) to `None` which means that by default, there is no logic that will exist on the entity (objects are normally entirely driven by their type so leaving to `None` means the least amount of logic occurs). This is what differentiate an [Item](ObjectTypes/Item.md) NPCControl which is a collectable [item entity](../EntityControl/Item%20entity.md) to an item SemiNPC which has no logic other than being a simple item entity that just happens to support interactions thanks to `SemiNPC` allowing it. Everything other than being interactable is either excluded from the NPCControl logic or is left practicaly useless. Effectively, it's a "dumb" item: it can only be interacted with when the player gets close enough, but nothing more.
|
||||
The basic idea of a SemiNPC is it behaves mostly like an [Object](NPCType.md#object), but it allows interactions. This is ideal for a shelved item because it's possible to leave the [objecttype](Object.md#objecttypes) to `None` which means that by default, there is no logic that will exist on the entity (objects are normally entirely driven by their type so leaving to `None` means the least amount of logic occurs). This is what differentiate an [Item](ObjectTypes/Item.md) NPCControl which is a collectable [item entity](../EntityControl/Item%20entity.md) to an item SemiNPC which has no logic other than being a simple item entity that just happens to support interactions thanks to `SemiNPC` allowing it. Everything other than being interactable is either excluded from the NPCControl logic or is left practicaly useless. Effectively, it's a "dumb" item: it can only be interacted with when the player gets close enough, but nothing more.
|
||||
|
||||
Additionall, this type has no OnTriggerEnter logic. This type shouldn't ever be loaded from map entity data because the shop system will create them when needed.
|
||||
|
||||
@@ -28,6 +29,7 @@ For an item shop, most of this happens during MapControl.CreateEntities while fo
|
||||
One additional thing to point out about `dialogues`: this array for a shop ends up either empty or of length 20. If the length of the array in the shop entity isn't 0, then the actual value is ignored and it will always be of length 20. This forces the game to load all the `dialogues` data elements that can exists. If the length is 0 however, none are loaded and the array remains empty. This however will cause unexpected behaviors and it is therefore not recommended to do so.
|
||||
|
||||
Here is how the data of the shop is defined on the main shop entity:
|
||||
|
||||
- `dialogues[0].y`: The [dialogue line id](../../SetText/Common%20commands%20id%20schemes/Dialogue%20line%20id.md) of the shop keeper when interacting with them (managed by the [ShopKeeper](Interaction/ShopKeeper.md) interaction)
|
||||
- `dialogues[1].y`: If it's 1, the shop accepts Crystal Berries instead of regular berries. NOTE: this won't behave as expected for a standard items shop, but it is technically supported by the game's data
|
||||
- `dialogues[2].y`: For a standard items shop, if it's higher than 0.1, the `mmulti` field (the buying price multiplier) of each shelved item will be this value / 10.0 (the result of the multiplication will be ceiled). This is read, but not used for a medals shop
|
||||
@@ -36,11 +38,12 @@ Here is how the data of the shop is defined on the main shop entity:
|
||||
- `dialogues[9].x`: For a medals shop, the medal shop id (only 0 and 1 exists under normal gameplay). This isn't used for a standard items shop
|
||||
- `dialogues[10].x`: This is 0 for all standard item shops and 1 for a medals shop (it is not possible to specify anything else which prevents key items from being supported)
|
||||
- `data.length`: The amount of shelved items
|
||||
- `data`: For a standard items shop, the list of [item](../../../Enums%20and%20IDs/Items.md) ids that the shop sells. This isn't used for a medals shop because the game manages them using the [shop available and pools arrays](../../External%20data%20format/Save%20File.md#line-4-array-line-medals-available-in-medal-shops) (the length is still used for the amount though)
|
||||
- `data`: For a standard items shop, the list of [item](../../Enums%20and%20IDs/Items.md) ids that the shop sells. This isn't used for a medals shop because the game manages them using the [shop available and pools arrays](../../External%20data%20format/Save%20File.md#line-4-array-line-medals-available-in-medal-shops) (the length is still used for the amount though)
|
||||
- `vectordata`: The list of the shelved items position where each index matches the corresponding `data` element
|
||||
|
||||
## Standard items shop specifics
|
||||
Here is how a shelved shop item gets created for each of them in MapControl.CreateEntities (all data pulled are from the shop keeper entity data):
|
||||
|
||||
- A new entity is created via [CreateNewEntity](../EntityControl/EntityControl%20Creation.md#createnewentity) named `FixedshopX` where X is the `data` index
|
||||
- The `startpos` gets set to the corresonding `vectordata` element
|
||||
- The `animid` gets set to `dialogues[10].x` (in practice however, this can only work with 0 as 1 will make it treat like a medals shop while 2 is invalid as it's a standard items shop, not a medals one)
|
||||
@@ -57,13 +60,14 @@ Here is how a shelved shop item gets created for each of them in MapControl.Crea
|
||||
- `colliderheight` is set to 0.5
|
||||
|
||||
On SetUp, there's 3 logic that will inevitably follow thanks to the `Shop` interaction and the `shopkeeper` being set for each shelved items:
|
||||
|
||||
- `mmulti` is set to a 1/10 of `shopkeeper.dialogues[2].y`, but if it's less than 0.1, it defaults to 1.0. This will later get used to multiply the item's price and the result will be ceiled.
|
||||
- CaravanMedalSet(false) is called which does the following:
|
||||
- entity.`rigid` gets its gravity disabled with all constraints frozen
|
||||
- The position is set to entity.`startpos`
|
||||
- entity.`ccol` is disabled
|
||||
- `descwindow` is destroyed if it existed
|
||||
- The `scol` is disabled
|
||||
- entity.`rigid` gets its gravity disabled with all constraints frozen
|
||||
- The position is set to entity.`startpos`
|
||||
- entity.`ccol` is disabled
|
||||
- `descwindow` is destroyed if it existed
|
||||
- The `scol` is disabled
|
||||
|
||||
## Medals shop specifics
|
||||
For this shop type, the only logic MapControl.CreateEntities does is set the the [interacttype](Interaction.md) of the original shop entity to [ShopKeeper](Interaction/ShopKeeper.md). All initialisation occurs in SeUp in 2 phases, one of the shop keeper and then one for each shelved items. The shelved items are initialised in the first phase then configured further on the second phase.
|
||||
@@ -74,6 +78,7 @@ For the first phase, thanks to `dialogues[10].x` being 1 and the [ShopKeeper](In
|
||||
The first thing it does is initialises `shopitems` to a new list of EntityControl of length `data.length`. This is used to keep references of the shelved items entities in case the method is called with refresh which causes the destructions of the shelved items before recreating them
|
||||
|
||||
From there, a loop is done from 0 to `data.length` exclusive to actually create the shelved items (the `data` array is never indexed directly):
|
||||
|
||||
- A new entity is created with name `badgeshopX` where X is the current index
|
||||
- `startpos` is set to the corresponding `vectordata`
|
||||
- `animid` is set to 2 (medal)
|
||||
@@ -93,13 +98,14 @@ From there, a loop is done from 0 to `data.length` exclusive to actually create
|
||||
|
||||
### Initialising the shelved shop items
|
||||
The second phase involves each shelved items on SetUp:
|
||||
|
||||
- `mmulti` is set to a 1/10 of `shopkeeper.dialogues[2].y`, but if it's less than 0.1, it defaults to 1.0. NOTE: this doesn't end up doing anything for a medals shop
|
||||
- CaravanMedalSet(false) is called which does the following:
|
||||
- entity.`rigid` gets its gravity disabled with all constraints frozen
|
||||
- The position is set to entity.`startpos`
|
||||
- entity.`ccol` is disabled
|
||||
- `descwindow` is destroyed if it existed
|
||||
- The `scol` is disabled
|
||||
- entity.`rigid` gets its gravity disabled with all constraints frozen
|
||||
- The position is set to entity.`startpos`
|
||||
- entity.`ccol` is disabled
|
||||
- `descwindow` is destroyed if it existed
|
||||
- The `scol` is disabled
|
||||
|
||||
### Refresh process
|
||||
Medals shop have a unique capability: it's possible for the game to recreate the entire shop by passing true instead of false to SetBadgeShop. This is notably used during a [kill](../../SetText/Individual%20commands/Kill.md) or [rerollshops](../../SetText/Individual%20commands/Rerollshops.md) SetText commands.
|
||||
|
||||
@@ -6,8 +6,9 @@ The entity.`ccol` and `scol` are initialised according to their [NPCType](NPCTyp
|
||||
From there, [SetUp](SetUp.md) is called which contains most of the startup logic.
|
||||
|
||||
After, a couple of specific logic occurs:
|
||||
|
||||
- The tag is set according to the [NPCType](NPCType.md)
|
||||
- The entity.`rigid` mass is changed according to the [NPCType](NPCType.md) except if it's an [item entity](../EntityControl/Item%20entity.md) where it remains 1.0
|
||||
- If applicable, the `disguiseobj` is initialised according to the [ActionBehaviors](ActionBehaviors.md)
|
||||
- The entire gameObject gets disabled if the `requires` and `limit` contain a violation. It also gets disabled when the entity.`hideinside` is true while the `insideid` does not match the current one
|
||||
- If the `NGF` [Modifier](../EntityControl/Modifiers.md) applies, [GravityFix](GravityFix.md) is started
|
||||
- If the `NGF` [Modifier](../EntityControl/Modifiers.md) applies, [GravityFix](Notable%20methods/GravityFix.md) is started
|
||||
@@ -1,16 +1,17 @@
|
||||
# Update
|
||||
Most of this event only happens if it's not a `dummy`, but some logic happens regardless at the end of it. The logic depends on the [NPCType](NPCType.md), [ObjectTypes](ObjectTypes.md) and [ActionBehaviors](ActionBehaviors.md). Consult each's documentation to learn more.
|
||||
Most of this event only happens if it's not a `dummy`, but some logic happens regardless at the end of it. The logic depends on the [NPCType](NPCType.md), [ObjectTypes](Object.md#objecttypes) and [ActionBehaviors](ActionBehaviors.md). Consult each's documentation to learn more.
|
||||
|
||||
## Non Dummy logic
|
||||
From there, the update logic depends whether the NPCControl is considered active or not. In order to be active, entity.`alwaysactive` needs to be true or all of the following needs to be true:
|
||||
|
||||
- The entity is `incamera`
|
||||
- The `insideid` matches the current one
|
||||
- From there, there are 3 cases:
|
||||
- `startlife` is less than 50 frames which makes the NPCControl active
|
||||
- The entity.`campos.z` is less than 25 when the map `limitbehavior` is false which makes the NPCControl active
|
||||
- The entity.`campos.z` is less than 15 when the map `limitbehavior` is true. In this case, the NPCControl is active only if any of the following are true:
|
||||
- The entity is currently in a [forcemove](../EntityControl/EntityControl%20Methods.md#forcemove)
|
||||
- The entity.`campos.x` is between 0.25 and 0.75 exclusive (it means it's centered enough to be within half the viewport horixontally)
|
||||
- `startlife` is less than 50 frames which makes the NPCControl active
|
||||
- The entity.`campos.z` is less than 25 when the map `limitbehavior` is false which makes the NPCControl active
|
||||
- The entity.`campos.z` is less than 15 when the map `limitbehavior` is true. In this case, the NPCControl is active only if any of the following are true:
|
||||
- The entity is currently in a [forcemove](../EntityControl/EntityControl%20Methods.md#forcemove)
|
||||
- The entity.`campos.x` is between 0.25 and 0.75 exclusive (it means it's centered enough to be within half the viewport horixontally)
|
||||
|
||||
If any of the above is violated, the NPCControl is considered inactive and implicates a different logic entirely.
|
||||
|
||||
@@ -19,6 +20,7 @@ There are 2 subsections to this. Up to one of them will apply with the main one
|
||||
|
||||
#### Main active update logic
|
||||
This Section only applies if any of the following are true:
|
||||
|
||||
- The entity is `activeinevents` while we are in a `minipause` or `inevent` and we aren't `trapped`
|
||||
- The entity is `activeonpause`
|
||||
- We aren't in a `pause`, `minipause`, [message](../../SetText/Notable%20states.md#message), the entity isn't an [item entity](../EntityControl/Item%20entity.md) and isn't `dead`, `iskill` and we aren't `trapped`
|
||||
@@ -31,28 +33,30 @@ Further [Enemy](NPCType.md#update-active-main-logic-no-overrides) exclusive logi
|
||||
|
||||
If `returntoheight` is true, the entity.`initialheight` is above 0.1, the entity.`height` is less than entity.`initialheight` - 0.05 and the `disguisecooldown` hasn't expired yet, entity.`height` is set to a lerp from entity.`height` to entity.`initialheight` with a factor of the frametime / 10. This also sets the entity.`oldfly` to false if its entity.`height` is less then entity.`initialheight` - 0.2 which forces a sprite update. All of this essentially makes the entity progressively comes back to its original height if applicable smoothly.
|
||||
|
||||
> If this this is an [Object](NPCType.md#object), then perform the Update specific section of the [ObjectTypes](ObjectTypes.md) which also replaces the rest of this section. Otherwise, the non object logic follows.
|
||||
> If this this is an [Object](Object.md), then perform the Update specific section of the [ObjectTypes](Object.md#objecttypes) which also replaces the rest of this section. Otherwise, the non object logic follows.
|
||||
|
||||
Further [Enemy](NPCType.md#update-active-main-logic-no-overrides) exclusive logic happens here when applicable.
|
||||
|
||||
Some logic specific to the [DisguiseOnce](ActionBehaviors/DisguiseOnce.md) behavior occurs here.
|
||||
|
||||
Finally, `hasenteredrange` is set to true and [DoBehavior](DoBehaviour.md) is called if all of the following conditions are true:
|
||||
Finally, `hasenteredrange` is set to true and [DoBehavior](Notable%20methods/DoBehaviour.md) is called if all of the following conditions are true:
|
||||
|
||||
- `overridebehavior` is false
|
||||
- No `behaviorroutine` is in progress
|
||||
- There is at least a default behavior set in `behaviors`
|
||||
- The entity isn't `dead` or `iskill` and doesn't have a `deathcoroutine` in progress
|
||||
- One of the following is true:
|
||||
- This is an [Enemy](NPCType.md#enemy)
|
||||
- The entity is `alwaysactive`
|
||||
- The entity.`campos.z` is less than 20.0 (it isn't too far forward the camera)
|
||||
- This is an [Enemy](Enemy.md)
|
||||
- The entity is `alwaysactive`
|
||||
- The entity.`campos.z` is less than 20.0 (it isn't too far forward the camera)
|
||||
|
||||
As for which behaviors is chosen at which frequency, it depends on 2 conditions:
|
||||
|
||||
- Whether or not `forcebehavior` is defined. This forces the behavior to use, but not the frequency (see the second condition for how that is selected)
|
||||
- Whether the player is present and its entity is `digging` or its entity.`icooldown` hasn't expired yet. If this is true, it forces the behavior AND the frequency to be the default one. Otherwise, the frequency depends on `inrange` and the behavior (assuming `forcebehavior` isn't defined) is also based on it.
|
||||
|
||||
#### Non trapped active item update logic
|
||||
This subsection applies if the main one didn't and it's an [item entity](../EntityControl/Item%20entity.md) while not being `trapped`. Most cases involves logic specific to the [Item](ObjectTypes/Item.md) object, but an [item entity](../EntityControl/Item%20entity.md) used as a shelved shop item is also affected, but not in a meaninful way (only calls [StopForceMove](../../EntityControl/EntityControl%20Methods.md#StopForceMove) on the 3rd cycle onward effectively making it fixed in place).
|
||||
This subsection applies if the main one didn't and it's an [item entity](../EntityControl/Item%20entity.md) while not being `trapped`. Most cases involves logic specific to the [Item](ObjectTypes/Item.md) object, but an [item entity](../EntityControl/Item%20entity.md) used as a shelved shop item is also affected, but not in a meaninful way (only calls [StopForceMove](../EntityControl/EntityControl%20Methods.md#stopforcemove) on the 3rd cycle onward effectively making it fixed in place).
|
||||
|
||||
### Inative updates
|
||||
This segment only applies if the entity is considered inactive which means the active update segmenets didn't apply.
|
||||
|
||||
@@ -39,8 +39,8 @@ As you can see, only the Data folder actually contains the game. The only thing
|
||||
Since this is where the actual game resides, we need to specifically talk about its structure.
|
||||
|
||||
* `Managed`: This folder contains all the compiled C# code (otherwise known as "Managed" code). Only 2 files are compiled from Unity: `Assembly-CSharp.dll` and `Assembly-CSharp-firstpass.dll`. The rest are all Unity's own library (which ends up interfacing with `UnityPlayer.dll`) and some core library needed for running .NET in unity (`System.dll`, `System.Core.dll`, `mscorlib.dll` and `Mono.Security.dll`). These files aren't present on consoles versions because it uses IL2CPP instead.
|
||||
* `Assembly-CSharp.dll`: This contains ALL the game's specific code. All the contents of this files are made by Moonsprout and it contains all the game's logic and every components's code.
|
||||
* `Assembly-CSharp-firstpass.dll`: This only contains the [Steamworks.NET](https://github.com/rlabrecque/Steamworks.NET) code which is open source and it allows to integrate Steamworks into Unity games. The reason for the name has to do with this being used as a plugin which requires a different step in the build process. `Assembly-CSharp.dll` refferences this file.
|
||||
* `Assembly-CSharp.dll`: This contains ALL the game's specific code. All the contents of this files are made by Moonsprout and it contains all the game's logic and every components's code.
|
||||
* `Assembly-CSharp-firstpass.dll`: This only contains the [Steamworks.NET](https://github.com/rlabrecque/Steamworks.NET) code which is open source and it allows to integrate Steamworks into Unity games. The reason for the name has to do with this being used as a plugin which requires a different step in the build process. `Assembly-CSharp.dll` refferences this file.
|
||||
* `Plugins`: This is where libraries loaded by the game are located. Only the Steam dll should be present which is provided by Valve through Steamworks. Steamworks.NET directly uses this file to invoke Steam's api.
|
||||
* `Ressources`: Only contains Unity's default ressources which is directly provided by Unity.
|
||||
* `app.info`: This is a simple file generated at build time containing the information provided to Unity at compilation which is the application name and the company name.
|
||||
|
||||
@@ -28,7 +28,8 @@ Otherwise, the [flagstring](../../Flags%20arrays/flagstring.md) 0 is set to the
|
||||
|
||||
* If we are, [flagstring](../../Flags%20arrays/flagstring.md) 0 is overridden to the MenuText line id 279 (which is "Lot of Items" in English), [flagvar](../../Flags%20arrays/flagvar.md) 10 is now the sum of each selected item's buying price / 2 floored clamped from 1 to 999. [Flags](../../Flags%20arrays/flags.md) 349 is now true
|
||||
* If we aren't, [flagvar](../../Flags%20arrays/flagvar.md) 10 is the buying price of the selected item / 2 floored clamped from 1 to 999.
|
||||
At any case, the list gets destroyed afterwards which ends this list's processing.
|
||||
|
||||
At any case, the list gets destroyed afterwards which ends this list's processing.
|
||||
|
||||
## Other behaviors (when unpaused)
|
||||
|
||||
|
||||
@@ -9,11 +9,11 @@ Display the list of open, taken or completed [BoardQuests](../../Enums%20and%20I
|
||||
* Leif's Request and Vi's Request are excluded (NOTE: Kabbu's Request should have been excluded, but its exclusion was forgotten).
|
||||
* Any story request (id between 11 and 17) are excluded.
|
||||
* Any of the following bounty requests are excluded if the current map isn't UndergroundBar and the board type of the list is the open quests:
|
||||
* Bounty: Seedling King
|
||||
* Bounty: False Monarch
|
||||
* Bounty: Devourer
|
||||
* Bounty: Tidal Wyrm
|
||||
* Bounty: Peacock Spider
|
||||
* Bounty: Seedling King
|
||||
* Bounty: False Monarch
|
||||
* Bounty: Devourer
|
||||
* Bounty: Tidal Wyrm
|
||||
* Bounty: Peacock Spider
|
||||
|
||||
If the end result has no quests, add quest id 0 (No Quests) as the only quest offered as option.
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@ The text string is rendered on the left side of the bar and it corresponds to th
|
||||
|24|256|Reset Control. Bindings|Does not render anything including the arrows|
|
||||
|
||||
\*: Here are all the pausemenu.joystick values with their corresponding text:
|
||||
|
||||
joystick | MenuText line id | Description
|
||||
------------ | -------- | ---------
|
||||
0 | 218 | DISABLED
|
||||
@@ -83,6 +84,7 @@ joystick | MenuText line id | Description
|
||||
5 | 230 | CUSTOM BINDINGS
|
||||
|
||||
\*\*: Here are all the pausemenu.joystickid values with their corresponding text when pausemenu.joystick is set to PRE-CONFIGURED:
|
||||
|
||||
joystickid | MenuText line id | Description
|
||||
------------ | -------- | ---------
|
||||
0 | 225 | Xbox 360
|
||||
|
||||
@@ -15,11 +15,11 @@ Check the individual [listtype](listtype.md) to learn more.
|
||||
## Rerendering after scroll
|
||||
|
||||
* if `listlow` isn't `listy` (meaning the list needs to be scrolled or it's a new ItemList) or [listtype](listtype.md) is the language selection list:
|
||||
* [Rerendering after scroll](ShowItemList%20Life%20Cycle/Rerendering%20after%20scroll.md)
|
||||
* [Rerendering after scroll](ShowItemList%20Life%20Cycle/Rerendering%20after%20scroll.md)
|
||||
|
||||
## `listdescbox` rendering
|
||||
|
||||
* if `showdescription` and `listvar` isn't empty.
|
||||
* Destroys the existing `listdescbox` if it isn't null.
|
||||
* [Description box rendering](ShowItemList%20Life%20Cycle/Description%20box%20rendering.md)
|
||||
* Destroys the existing `listdescbox` if it isn't null.
|
||||
* [Description box rendering](ShowItemList%20Life%20Cycle/Description%20box%20rendering.md)
|
||||
* Sets the ItemList's localEulerAngle to Vector3.zero.
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
* If the [listtype](../listtype.md) isn't a questboard list
|
||||
* **Determine the text to render and if we are going to render at all via [SetText](../../SetText/SetText.md) according to the [listtype](../listtype.md)**
|
||||
* Create a white 9Box at the bottom left portion of the screen that will have the description
|
||||
* If `sell`:
|
||||
* Set the HUD to show the berry count.
|
||||
* Set [flagvar](../../Flags%20arrays/flagvar.md) 10 to half the buying price rounded down of the item obtained from `itemdata` according to the [listtype](../listtype.md) as the item type and `option` as the item id clamped from 1 to 999.
|
||||
* Prepend the input string prepared earlier with the secondary string obtained earlier followed by `-` + the sell price display line with a [Currency](../../SetText/Individual%20commands/Currency.md) command at MenuText 49 + |[line](../../SetText/Individual%20commands/Line.md)\|
|
||||
* Calls [SetText](../../SetText/SetText.md) in non [Dialogue mode](../../SetText/Dialogue%20mode.md) with the following:
|
||||
* \|[single](../../SetText/Individual%20commands/Single.md)\||[singlebreak](../../SetText/Individual%20commands/Singlebreak.md), + itemdescbreak (This is 10.5 normally) + `|` + the final text determined earlier
|
||||
* `BubblegumSans` font
|
||||
* no linebreak
|
||||
* no tridimensional
|
||||
* position at (-5.25, 0.6)
|
||||
* no cameraoffset
|
||||
* size at (0.75, 0.75)
|
||||
* parent is the 9Box created earlier
|
||||
* no caller
|
||||
* Set `listdescbox` as the 9Box created earlier.
|
||||
* **Determine the text to render and if we are going to render at all via [SetText](../../SetText/SetText.md) according to the [listtype](../listtype.md)**
|
||||
* Create a white 9Box at the bottom left portion of the screen that will have the description
|
||||
* If `sell`:
|
||||
* Set the HUD to show the berry count.
|
||||
* Set [flagvar](../../Flags%20arrays/flagvar.md) 10 to half the buying price rounded down of the item obtained from `itemdata` according to the [listtype](../listtype.md) as the item type and `option` as the item id clamped from 1 to 999.
|
||||
* Prepend the input string prepared earlier with the secondary string obtained earlier followed by `-` + the sell price display line with a [Currency](../../SetText/Individual%20commands/Currency.md) command at MenuText 49 + |[line](../../SetText/Individual%20commands/Line.md)\|
|
||||
* Calls [SetText](../../SetText/SetText.md) in non [Dialogue mode](../../SetText/Dialogue%20mode.md) with the following:
|
||||
* \|[single](../../SetText/Individual%20commands/Single.md)\||[singlebreak](../../SetText/Individual%20commands/Singlebreak.md), + itemdescbreak (This is 10.5 normally) + `|` + the final text determined earlier
|
||||
* `BubblegumSans` font
|
||||
* no linebreak
|
||||
* no tridimensional
|
||||
* position at (-5.25, 0.6)
|
||||
* no cameraoffset
|
||||
* size at (0.75, 0.75)
|
||||
* parent is the 9Box created earlier
|
||||
* no caller
|
||||
* Set `listdescbox` as the 9Box created earlier.
|
||||
* If the currently selected quest isn't None:
|
||||
* Create the `listdescbox`.
|
||||
* Render an image of the quest id `option`'s author using `librarysprites` from the index obtained in [BoardQuestData](../../TextAsset%20Data/BoardQuests%20data.md#BoardQuests%20data) which will have a name of `Image` and a tag of `Text`.
|
||||
* Calls [SetText](../../SetText/SetText.md) with the following in non [Dialogue mode](../../SetText/Dialogue%20mode.md):
|
||||
* `text`: |[size](../../SetText/Individual%20commands/size.md),0.75||[sort](../../SetText/Individual%20commands/Sort.md),1| + The `By:` from MenuText 104 + ` ` + The author of the quest id `option` obtained from `boardquestdata` + |[line](../../SetText/Individual%20commands/Line.md)\||[halfline](../../SetText/Individual%20commands/Halfline.md)\| + The `Difficulty:` from MenuText 105 + ` ` + |[Stars](../../SetText/Individual%20commands/Stars.md), + The amount of filled in stars of the quest id `option` obtained from `boardquestdata` + `|`.
|
||||
* `position`: (12, 0.35).
|
||||
* `parent`: `listdescbox`.
|
||||
* Create the `listdescbox`.
|
||||
* Render an image of the quest id `option`'s author using `librarysprites` from the index obtained in [BoardQuestData](../../TextAsset%20Data/BoardQuests%20data.md#BoardQuests%20data) which will have a name of `Image` and a tag of `Text`.
|
||||
* Calls [SetText](../../SetText/SetText.md) with the following in non [Dialogue mode](../../SetText/Dialogue%20mode.md):
|
||||
* `text`: |[size](../../SetText/Individual%20commands/size.md),0.75||[sort](../../SetText/Individual%20commands/Sort.md),1| + The `By:` from MenuText 104 + ` ` + The author of the quest id `option` obtained from `boardquestdata` + |[line](../../SetText/Individual%20commands/Line.md)\||[halfline](../../SetText/Individual%20commands/Halfline.md)\| + The `Difficulty:` from MenuText 105 + ` ` + |[Stars](../../SetText/Individual%20commands/Stars.md), + The amount of filled in stars of the quest id `option` obtained from `boardquestdata` + `|`.
|
||||
* `position`: (12, 0.35).
|
||||
* `parent`: `listdescbox`.
|
||||
|
||||
@@ -4,16 +4,16 @@
|
||||
* Resets [ItemList](../ItemList.md) to a new GameObject, set its parent to the GUICamera or to the `questboardobj` if it isn't null and set its localPosition to (`position`.x, `position`.y, 10.0).
|
||||
* If [listtype](../listtype.md) is the language selection list, Call [SetText](../../SetText/SetText.md) in non [Dialogue mode](../../SetText/Dialogue%20mode.md) where the text is set to the language selection prompt using the index of option of `listvar` prepended with |[color](../../SetText/Individual%20commands/Color.md),4||[center](../../SetText/Individual%20commands/Center.md)\||[sort](../../SetText/Individual%20commands/Sort.md),20|. This effectively changes the line to match the selected language.
|
||||
* If `listlow` is above 0 and `maxoptions` is higher than `listammount` (which means that there are more items than visible at once and we have scrolled below the top):
|
||||
* Setup the up arrow GUI sprite to appear at the top of the list as child of ItemList. The exact setup depends on [listtype](../listtype.md) and if we are in the pause menu.
|
||||
* Setup the up arrow GUI sprite to appear at the top of the list as child of ItemList. The exact setup depends on [listtype](../listtype.md) and if we are in the pause menu.
|
||||
* If we had a list in `overridedlist`, restore it and clear it.
|
||||
* If we allow multi select `listsell` is true OR [listtype](../listtype.md) is storage items OR ([listtype](../listtype.md) is standard items and [flags](../../Flags%20arrays/flags.md) 349 is on), then setup the UI to instruct how to operate multiple selection.
|
||||
* For each index in the visible part of the ItemList that does not exceed `maxoptions` (this means an empty ItemList will have no iteration):
|
||||
* Setup the SpriteRenderer that will contain the option as child of the ItemList. A 75% opaque rectangle will be rendered as background if we aren't paused and the [listtype](../listtype.md) isn't one about quests, settings, language list or input lists (color is green if it is in `multiselect` or white otherwise). The layer is set to 5, scaled by 1.15 in x when not paused and the position is relative to its index.
|
||||
* Set the default rendering param to send to [SetText](../../SetText/SetText.md) that can be overridden by [listtype](../listtype.md): x is -2, y is -0.15 and size is (0.75, 0.75).
|
||||
* **Obtain the text of the option according to [listtype](../listtype.md)**.
|
||||
* Calls [SetText](../../SetText/SetText.md) in non [Dialogue mode](../../SetText/Dialogue%20mode.md) using the `BubblegumSans` font in non tridimensional at the position and size determined earlier without a Camoffset with the SpriteRenderer as the parent and without a caller with the text prepended with:
|
||||
* \|[size](../../SetText/Individual%20commands/size.md),0.6,0.8| when unpaused
|
||||
* Nothing if paused and [listtype](../listtype.md) is not the current medals list
|
||||
* ` ` otherwise.
|
||||
* Setup the SpriteRenderer that will contain the option as child of the ItemList. A 75% opaque rectangle will be rendered as background if we aren't paused and the [listtype](../listtype.md) isn't one about quests, settings, language list or input lists (color is green if it is in `multiselect` or white otherwise). The layer is set to 5, scaled by 1.15 in x when not paused and the position is relative to its index.
|
||||
* Set the default rendering param to send to [SetText](../../SetText/SetText.md) that can be overridden by [listtype](../listtype.md): x is -2, y is -0.15 and size is (0.75, 0.75).
|
||||
* **Obtain the text of the option according to [listtype](../listtype.md)**.
|
||||
* Calls [SetText](../../SetText/SetText.md) in non [Dialogue mode](../../SetText/Dialogue%20mode.md) using the `BubblegumSans` font in non tridimensional at the position and size determined earlier without a Camoffset with the SpriteRenderer as the parent and without a caller with the text prepended with:
|
||||
* \|[size](../../SetText/Individual%20commands/size.md),0.6,0.8| when unpaused
|
||||
* Nothing if paused and [listtype](../listtype.md) is not the current medals list
|
||||
* ` ` otherwise.
|
||||
* If the [ItemList](../ItemList.md) isn't scrolled such that the bottom is visible:
|
||||
* Setup the down arrow GUI sprite to appear at the bottom of the ItemList as child of the `ItemList`. The exact setup depends on [listtype](../listtype.md) and if we are in the pause menu.
|
||||
* Setup the down arrow GUI sprite to appear at the bottom of the ItemList as child of the `ItemList`. The exact setup depends on [listtype](../listtype.md) and if we are in the pause menu.
|
||||
|
||||
@@ -26,8 +26,8 @@ In its simplest form, this command will evaluate the following:
|
||||
|
||||
* If syntax (1) and `flags` is one [flag](../../Flags%20arrays/flags.md) slot, check if that slot is false
|
||||
* If syntax (1) and `flags` is an array of integer, for each int:
|
||||
* if it is above 0, check if the corresponding [flag](../../Flags%20arrays/flags.md) slot is false
|
||||
* If it is 0 or below, take the absolute value and check if the corresponding [flag](../../Flags%20arrays/flags.md) slot is true
|
||||
* if it is above 0, check if the corresponding [flag](../../Flags%20arrays/flags.md) slot is false
|
||||
* If it is 0 or below, take the absolute value and check if the corresponding [flag](../../Flags%20arrays/flags.md) slot is true
|
||||
* If Syntax (2), check that the [flagvar](../../Flags%20arrays/flagvar.md) slot `flagvar` is NOT equal to `value`
|
||||
|
||||
If any the applicable conditions are false, this command will do nothing and processing resumes as normal.
|
||||
|
||||
@@ -48,8 +48,8 @@ In its simplest form, this command will evaluate the following:
|
||||
|
||||
* If syntax (1) and `flags` is one [flags](../../Flags%20arrays/flags.md) slot, check if that slot is true
|
||||
* If syntax (1) and `flags` is an array of integer, for each int:
|
||||
* if it is above 0, check if the corresponding [flags](../../Flags%20arrays/flags.md) slot is true
|
||||
* If it is 0 or below, take the absolute value and check if the corresponding [flags](../../Flags%20arrays/flags.md) slot is false
|
||||
* if it is above 0, check if the corresponding [flags](../../Flags%20arrays/flags.md) slot is true
|
||||
* If it is 0 or below, take the absolute value and check if the corresponding [flags](../../Flags%20arrays/flags.md) slot is false
|
||||
* If Syntax (2), check that the [flagvar](../../Flags%20arrays/flagvar.md) slot `flagvar` is NOT equal to `value`
|
||||
|
||||
If any the applicable conditions are false, this command will do nothing and processing resumes as normal.
|
||||
|
||||
@@ -115,14 +115,14 @@ A description box will be created if `itemtype` isn't berries or Crystal Berries
|
||||
* Create a pure white standard 9box of type 0 relatively positioned at (0.0, -4.4, 10.0) of the GUICamera with a size of (11.0, 3.0) with a sort order of -3 with a grow animation and assign it to descwindow
|
||||
* Sets [flagvar](../../Flags%20arrays/flagvar.md) 10 to the buying price price of the [item](../../Enums%20and%20IDs/Items.md) or [medal](../../Enums%20and%20IDs/Medal.md)
|
||||
* Calls SetText in [non Dialogue mode](../Dialogue%20mode.md#non-dialogue-mode) with the input string |[single](Single.md)\||[singlebreak](Singlebreak.md),`itemdescbreak`\| where `itemdescbreak` is 10.5 on `English` and 9.9 on any other language followed by the [item](../../Enums%20and%20IDs/Items.md) or [medal](../../Enums%20and%20IDs/Medal.md) description:
|
||||
* Font is `BubblegumSans`
|
||||
* No line breaks (this is already manually controlled via the input string)
|
||||
* No tridimensional
|
||||
* Position is (-5.2, 0.65, 1.0)
|
||||
* No camera offset
|
||||
* Size is (0.675, 0.675)
|
||||
* Parent is the descwindow created earlier
|
||||
* No caller
|
||||
* Font is `BubblegumSans`
|
||||
* No line breaks (this is already manually controlled via the input string)
|
||||
* No tridimensional
|
||||
* Position is (-5.2, 0.65, 1.0)
|
||||
* No camera offset
|
||||
* Size is (0.675, 0.675)
|
||||
* Parent is the descwindow created earlier
|
||||
* No caller
|
||||
|
||||
### Other rendering setup
|
||||
|
||||
@@ -130,8 +130,8 @@ A description box will be created if `itemtype` isn't berries or Crystal Berries
|
||||
* Stop the `entity` rigidBody's velocity
|
||||
* Setup an array of 3 SpriteRender
|
||||
* Assign the first element of the array to the sprite of the item named `tempitem` (the sprite is gui sprite 83 (the Crystal Berry icon) if `itemtype` is Crystal Berry and for berries, it's the berry sprite with the highest value that fits in the amount from `itemid`)
|
||||
* This is positioned at the `entity`'s location + (0.0, 2.75, -0.1) at the same angles than the camera.
|
||||
* The layer is set to 14
|
||||
* This is positioned at the `entity`'s location + (0.0, 2.75, -0.1) at the same angles than the camera.
|
||||
* The layer is set to 14
|
||||
* Assign the second element of the array to a new object named `fauxmessage` at (0.0, 3.0, 10.0) from the GUICamera using the [boxstyle](Boxstyle.md) 4
|
||||
* Create a new SpriteRender named `back` childed to `tempitem` at (0.0, 0.0, 0.2) with no rotation using gui sprite 85 (this is the star shaped background rendered behind the item)
|
||||
* Set the layer of `back` to 14 and its scale to Vector3.zero with a grow animation (this effectively setup a grow while the sprite is hidden at first).
|
||||
@@ -165,5 +165,5 @@ The `itemtype` have their own specific logic:
|
||||
### Redirection
|
||||
|
||||
* If `itemtype` is Medal and [flag](../../Flags%20arrays/flags.md) 31 is false (the player has yet to receive the medal tutorial):
|
||||
* Assign a string with the value |[tail](Tail.md),null||[destroydescbox](Destroydescbox.md)\||[blank](Blank.md)\||[boxstyle](Boxstyle.md),4| followed by common dialogue 31 (the medal tutorial) followed by |[flag](Flag.md),31,true||[break](Break.md)\||[gettail](Gettail.md),`tailid`\||[boxstyle](Boxstyle.md),0| where `tailid` is the current [tailtarget](../Notable%20states.md#tailtarget).
|
||||
* Assign a string with the value |[tail](Tail.md),null||[destroydescbox](Destroydescbox.md)\||[blank](Blank.md)\||[boxstyle](Boxstyle.md),4| followed by common dialogue 31 (the medal tutorial) followed by |[flag](Flag.md),31,true||[break](Break.md)\||[gettail](Gettail.md),`tailid`\||[boxstyle](Boxstyle.md),0| where `tailid` is the current [tailtarget](../Notable%20states.md#tailtarget).
|
||||
* Assign the input string to an [OrganiseLines](../Related%20Systems/Automatic%20Line%20Breaks/OrganiseLines.md) version of `redirect` prepanded with |[destroydescbox](Destroydescbox.md)\||[blank](Blank.md)\| all prepanded with the medal tutorial if it was assigned above.
|
||||
|
||||
@@ -107,24 +107,24 @@ To render each options (the letters, Erase, Space and Confirm), the following is
|
||||
|
||||
* Start with the x and y position of the options be -6.35 and 1.8 respectively
|
||||
* Render the options such that for each character in the letter prompt data (which is the value of [flagstring](../../Flags%20arrays/flagstring.md) 1 at this point):
|
||||
* If we encounter an LF:
|
||||
* Reset the x position to -6.35
|
||||
* Remove a certain amount from the y position. This amount is 0.75 if we aren't in the Korean letter prompt or 1.1 if we are and it's not the 4th line.
|
||||
* Set to no longer increment [flagvar](../../Flags%20arrays/flagvar.md) 1.
|
||||
* If we have yet to encounter the first LF:
|
||||
* Increment [flagvar](../../Flags%20arrays/flagvar.md) 1 (this means each row must have the same amount of options max than the first row as this value is going to be the number of options per row)
|
||||
* Have the option text be |[choicewave](Choicewave.md),n,true| where n is `maxoptions`.
|
||||
* Increment `maxoptions`.
|
||||
* Call [SetText](../SetText.md) in non [Dialogue mode](../Dialogue%20mode.md) using the text with |[center](Center.md)\|:
|
||||
* [fonttype](../Notable%20states.md#Notable%20states.md#fonttype) is `BubblegumSans`
|
||||
* no `linebreak`
|
||||
* no `tridimensional`
|
||||
* `position` is (x, y, 0.0) where x and y are the current value of the option's positions.
|
||||
* no `camoffset`
|
||||
* `size` of (1.0, 1.0)
|
||||
* `parent` is the `promptbox`
|
||||
* no `caller`
|
||||
* Add 0.65 to x
|
||||
* If we encounter an LF:
|
||||
* Reset the x position to -6.35
|
||||
* Remove a certain amount from the y position. This amount is 0.75 if we aren't in the Korean letter prompt or 1.1 if we are and it's not the 4th line.
|
||||
* Set to no longer increment [flagvar](../../Flags%20arrays/flagvar.md) 1.
|
||||
* If we have yet to encounter the first LF:
|
||||
* Increment [flagvar](../../Flags%20arrays/flagvar.md) 1 (this means each row must have the same amount of options max than the first row as this value is going to be the number of options per row)
|
||||
* Have the option text be |[choicewave](Choicewave.md),n,true| where n is `maxoptions`.
|
||||
* Increment `maxoptions`.
|
||||
* Call [SetText](../SetText.md) in non [Dialogue mode](../Dialogue%20mode.md) using the text with |[center](Center.md)\|:
|
||||
* [fonttype](../Notable%20states.md#Notable%20states.md#fonttype) is `BubblegumSans`
|
||||
* no `linebreak`
|
||||
* no `tridimensional`
|
||||
* `position` is (x, y, 0.0) where x and y are the current value of the option's positions.
|
||||
* no `camoffset`
|
||||
* `size` of (1.0, 1.0)
|
||||
* `parent` is the `promptbox`
|
||||
* no `caller`
|
||||
* Add 0.65 to x
|
||||
|
||||
After all the letters have been rendered, [flagstring](../../Flags%20arrays/flagstring.md) 1 will have its LF and { removed.
|
||||
|
||||
@@ -137,6 +137,7 @@ After all the letters have been rendered, [flagstring](../../Flags%20arrays/flag
|
||||
After, the help text to the next letter prompt with the switch button is rendered by creating a new GameObject parented to the `promptbox` called `button` with a ButtonSprite set to `Scroll Faster / Switch Party` whose label is the corresponding letterPromptHelp at the current id at (-2.25, -1.9) and a size of (0.5, 0.5).
|
||||
|
||||
After the initial setup, the first refresh of the letter prompt is performed. This will destroy the text in `npromptholder` and rerender using the one in [flagstring](../../Flags%20arrays/flagstring.md) 0 which will get updated periodically as letters are added or removed during the prompt handling. This also sets [flagvar](../../Flags%20arrays/flagvar.md) 4 to 0. As for the rendering of the text itself, it is done via a SetText call in non [Dialogue mode](../Dialogue%20mode.md) with the text padded to the right with `_` to fit into `maxlength` prepended with |[center](Center.md)\|:
|
||||
|
||||
- [fonttype](../Notable%20states.md#Notable%20states.md#fonttype) is `BubblegumSans`
|
||||
- no linebreak
|
||||
- no tridimensional
|
||||
@@ -179,16 +180,16 @@ For other inputs, they are restricted to the following:
|
||||
* Switch: Rerender the letter prompt, but the id is now the current one + 1 or go back to 0 on the last one
|
||||
* Cancel: Sets `listcancelled` to true. Then, if there are no letters entered, play the buzzer. Otherwise, the last character of the `flagstring` is removed and the letter prompt refreshed. This also resets the Korean prompt to its original state if we are in it
|
||||
* Confirm: `listcancelled` is set to false, a 5 frames input cooldown is applied and it also set `promptpick` to 0. The rest depends on the option currently selected before resetting the [Backtracking](../Related%20Systems/Backtracking.md) system:
|
||||
* A letter: Add the entered letter to [flagstring](../../Flags%20arrays/flagstring.md) 0 (current text) and refresh the letter prompt unless the length is `maxlength` from [flagvar](../../Flags%20arrays/flagvar.md) 10 in which case, the buzzer plays.
|
||||
* For the Korean prompt, the option must be within the current accepted section's range or the buzzer will play ([flagvar](../../Flags%20arrays/flagvar.md) 6 tells the current one, the accepted options ranges per sections are hardcoded). If it is in the valid range, then it depends on the current section:
|
||||
* Not last: [flagvar](../../Flags%20arrays/flagvar.md) 6 is incremented.
|
||||
* Last: [flagvar](../../Flags%20arrays/flagvar.md) 6 is reset to 0, the cumulation of all the letter selected in each sections is appended to [flagstring](../../Flags%20arrays/flagstring.md) 0, the current letter selections is cleared and the option index is reset to 0.
|
||||
* No matter what, if the selection was accepted, the prompt is refreshed and the Korean prompt logic is also refreshed
|
||||
* Erase: Remove the last entered letter from [flagstring](../../Flags%20arrays/flagstring.md) 0 (current text) and refresh the letter prompt unless the text was empty in which case, the buzzer plays.
|
||||
* For the Korean prompt, it also resets [flagvar](../../Flags%20arrays/flagvar.md) 6 (current section) to 0, clears the current selection and refresh the Korean prompt logic.
|
||||
* Space: Add a ` ` to [flagstring](../../Flags%20arrays/flagstring.md) 0 (current text) and refresh the letter prompt unless the length is `maxlength` from [flagvar](../../Flags%20arrays/flagvar.md) 10 or we are during a Korean prompt character selection ([flagvar](../../Flags%20arrays/flagvar.md) 6 is higher than 0) in which case, the buzzer plays.
|
||||
* Confirm: If [flagstring](../../Flags%20arrays/flagstring.md) 0 (current text) is empty, the buzzer is played, otherwise:
|
||||
* `promptpointers` is set to one element containing `confirmline` fetched from `listredirect`, [Text advance](../Related%20Systems/Text%20advance.md)'s `skiptext` is set to false and finally, the `prompt` lock is released
|
||||
* A letter: Add the entered letter to [flagstring](../../Flags%20arrays/flagstring.md) 0 (current text) and refresh the letter prompt unless the length is `maxlength` from [flagvar](../../Flags%20arrays/flagvar.md) 10 in which case, the buzzer plays.
|
||||
* For the Korean prompt, the option must be within the current accepted section's range or the buzzer will play ([flagvar](../../Flags%20arrays/flagvar.md) 6 tells the current one, the accepted options ranges per sections are hardcoded). If it is in the valid range, then it depends on the current section:
|
||||
* Not last: [flagvar](../../Flags%20arrays/flagvar.md) 6 is incremented.
|
||||
* Last: [flagvar](../../Flags%20arrays/flagvar.md) 6 is reset to 0, the cumulation of all the letter selected in each sections is appended to [flagstring](../../Flags%20arrays/flagstring.md) 0, the current letter selections is cleared and the option index is reset to 0.
|
||||
* No matter what, if the selection was accepted, the prompt is refreshed and the Korean prompt logic is also refreshed
|
||||
* Erase: Remove the last entered letter from [flagstring](../../Flags%20arrays/flagstring.md) 0 (current text) and refresh the letter prompt unless the text was empty in which case, the buzzer plays.
|
||||
* For the Korean prompt, it also resets [flagvar](../../Flags%20arrays/flagvar.md) 6 (current section) to 0, clears the current selection and refresh the Korean prompt logic.
|
||||
* Space: Add a ` ` to [flagstring](../../Flags%20arrays/flagstring.md) 0 (current text) and refresh the letter prompt unless the length is `maxlength` from [flagvar](../../Flags%20arrays/flagvar.md) 10 or we are during a Korean prompt character selection ([flagvar](../../Flags%20arrays/flagvar.md) 6 is higher than 0) in which case, the buzzer plays.
|
||||
* Confirm: If [flagstring](../../Flags%20arrays/flagstring.md) 0 (current text) is empty, the buzzer is played, otherwise:
|
||||
* `promptpointers` is set to one element containing `confirmline` fetched from `listredirect`, [Text advance](../Related%20Systems/Text%20advance.md)'s `skiptext` is set to false and finally, the `prompt` lock is released
|
||||
|
||||
### Handling the letter prompt outcome
|
||||
|
||||
|
||||
@@ -74,23 +74,24 @@ To render each 12 options (the 10 digits, Confirm and Erase), the following is d
|
||||
|
||||
* Start with the x and y position of the options be -2.25 and -0.25 respectively
|
||||
* Render the options such that for each options:
|
||||
* Have each text be |[choicewave](Choicewave.md),n,true| where n is the option index from 0 to 11. This is prepanded with menutext 42 (`Confirm`) for option 10 and menutext 74 (`Erase`) for option 11. Option 0-9 are the digits.
|
||||
* Call [SetText](../SetText.md) in [non Dialogue mode](../Dialogue%20mode.md#non-dialoguie-mode) using the text prepanded with |[center](Center.md)\|:
|
||||
* [fonttype](../Notable%20states.md#fonttype) is `BubblegumSans`
|
||||
* no `linebreak`
|
||||
* no `tridimensional`
|
||||
* `position` is (x, y, 0.0) where x and y are the current value of the option's positions.
|
||||
* no `camoffset`
|
||||
* `size` of (0.85, 0.85)
|
||||
* `parent` is the promptbox
|
||||
* no `caller`
|
||||
* Add 0.5 to x
|
||||
* if we had just rendered option 9
|
||||
* Remove -1.5 to x and 0.75 to y
|
||||
* If we had just rendered option 10
|
||||
* Set x to 1.5
|
||||
* Have each text be |[choicewave](Choicewave.md),n,true| where n is the option index from 0 to 11. This is prepanded with menutext 42 (`Confirm`) for option 10 and menutext 74 (`Erase`) for option 11. Option 0-9 are the digits.
|
||||
* Call [SetText](../SetText.md) in [non Dialogue mode](../Dialogue%20mode.md#non-dialoguie-mode) using the text prepanded with |[center](Center.md)\|:
|
||||
* [fonttype](../Notable%20states.md#fonttype) is `BubblegumSans`
|
||||
* no `linebreak`
|
||||
* no `tridimensional`
|
||||
* `position` is (x, y, 0.0) where x and y are the current value of the option's positions.
|
||||
* no `camoffset`
|
||||
* `size` of (0.85, 0.85)
|
||||
* `parent` is the promptbox
|
||||
* no `caller`
|
||||
* Add 0.5 to x
|
||||
* if we had just rendered option 9
|
||||
* Remove -1.5 to x and 0.75 to y
|
||||
* If we had just rendered option 10
|
||||
* Set x to 1.5
|
||||
|
||||
After the initial setup, the first refresh of the number prompt is performed. This will destroy the text in `npromptholder` and rerender using the one in [flagstring](../../Flags%20arrays/flagstring.md) 0 which will get updated periodically as digits are added in removed during the prompt handling. This also sets [flagvar](../../Flags%20arrays/flagvar.md) 4 to 0. As for the rendering of the number text itself, it is done via a SetText call in non [Dialogue mode](../Dialogue%20mode.md) with the text padded to the right with `_` to fit into `maxlength` prepended with |[center](Center.md)\|:
|
||||
|
||||
- [fonttype](../Notable%20states.md#Notable%20states.md#fonttype) is `BubblegumSans`
|
||||
- no `linebreak`
|
||||
- no `tridimensional`
|
||||
@@ -115,11 +116,11 @@ The actions will be restricted to the following:
|
||||
* Pause: Move the cursor to the confirm option
|
||||
* Cancel: Sets `listcancelled` to true, `promptpick` to 0, `promptpointers` to be one element containing `cancelline` fetched from `listcancel` and [Text advance](../Related%20Systems/Text%20advance.md)'s `skiptext` to false. This will also apply a 15 frames inputcooldown, reset the [Backtracking](../Related%20Systems/Backtracking.md) system and finally, release the `prompt` lock
|
||||
* Confirm: A 5 frames input cooldown is applied and it also set `promptpick` to 0. The rest depends on the option currently selected before resetting the [Backtracking](../Related%20Systems/Backtracking.md) system:
|
||||
* A number: Add the entered digit to [flagstring](../../Flags%20arrays/flagstring.md) 0 (current number text) and refresh the number prompt unless the length is `maxlength` from [flagvar](../../Flags%20arrays/flagvar.md) 10 in which case, the buzzer plays
|
||||
* Erase: Remove the last entered digit from [flagstring](../../Flags%20arrays/flagstring.md) 0 (current number text) and refresh the number prompt unless the text was empty in which case, the buzzer plays
|
||||
* Confirm: If [flagstring](../../Flags%20arrays/flagstring.md) 0 (current number text) is empty
|
||||
* This is treated the same way than if cancel was pressed with the exception that the input cooldown is 5 frames instead of 15 and `listcancelled` isn't set to false.
|
||||
* If it wasn't empty, the `outflagvar` [flagvar](../../Flags%20arrays/flagvar.md) slot is set to the integer version of [flagstring](../../Flags%20arrays/flagstring.md) 0 (the current number text), `promptpointers` is set to one element containing `confirmline` fetched from `listredirect`, [Text advance](../Related%20Systems/Text%20advance.md)'s `skiptext` is set to false, the [Backtracking](../Related%20Systems/Backtracking.md) system is reset and finally, the `prompt` lock is released
|
||||
* A number: Add the entered digit to [flagstring](../../Flags%20arrays/flagstring.md) 0 (current number text) and refresh the number prompt unless the length is `maxlength` from [flagvar](../../Flags%20arrays/flagvar.md) 10 in which case, the buzzer plays
|
||||
* Erase: Remove the last entered digit from [flagstring](../../Flags%20arrays/flagstring.md) 0 (current number text) and refresh the number prompt unless the text was empty in which case, the buzzer plays
|
||||
* Confirm: If [flagstring](../../Flags%20arrays/flagstring.md) 0 (current number text) is empty
|
||||
* This is treated the same way than if cancel was pressed with the exception that the input cooldown is 5 frames instead of 15 and `listcancelled` isn't set to false.
|
||||
* If it wasn't empty, the `outflagvar` [flagvar](../../Flags%20arrays/flagvar.md) slot is set to the integer version of [flagstring](../../Flags%20arrays/flagstring.md) 0 (the current number text), `promptpointers` is set to one element containing `confirmline` fetched from `listredirect`, [Text advance](../Related%20Systems/Text%20advance.md)'s `skiptext` is set to false, the [Backtracking](../Related%20Systems/Backtracking.md) system is reset and finally, the `prompt` lock is released
|
||||
|
||||
### Handling the number prompt outcome
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user