sonolus.script.archetype¶
ArchetypeLife
¶
Bases: Record
How an entity contributes to life.
good_increment: int
instance-attribute
¶
Life increment for a good judgment.
great_increment: int
instance-attribute
¶
Life increment for a great judgment.
miss_increment: int
instance-attribute
¶
Life increment for a miss judgment.
perfect_increment: int
instance-attribute
¶
Life increment for a perfect judgment.
__pos__() -> Self
¶
Return a copy of the record.
type_var_value(var: TypeVar) -> Any
classmethod
¶
Return the value of a type variable.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
var
|
TypeVar
|
The type variable to get the value of. |
required |
Returns:
Type | Description |
---|---|
Any
|
The value of the type variable. |
update(perfect_increment: int | None = None, great_increment: int | None = None, good_increment: int | None = None, miss_increment: int | None = None)
¶
Update the life increments.
EntityRef
¶
Bases: Record
Reference to another entity.
May be used with typing.Any
to reference an unknown archetype.
Usage
class MyArchetype(PlayArchetype):
ref_1: EntityRef[OtherArchetype] = imported()
ref_2: EntityRef[Any] = imported()
__pos__() -> Self
¶
Return a copy of the record.
archetype() -> type[A]
classmethod
¶
Get the archetype type.
archetype_matches() -> bool
¶
Check if entity at the index is precisely of the archetype.
get() -> A
¶
Get the entity.
get_as(archetype: type[_BaseArchetype]) -> _BaseArchetype
¶
Get the entity as the given archetype type.
type_var_value(var: TypeVar) -> Any
classmethod
¶
Return the value of a type variable.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
var
|
TypeVar
|
The type variable to get the value of. |
required |
Returns:
Type | Description |
---|---|
Any
|
The value of the type variable. |
with_archetype(archetype: type[T]) -> EntityRef[T]
¶
Return a new reference with the given archetype type.
PlayArchetype
¶
Bases: _BaseArchetype
Base class for play mode archetypes.
Usage
class MyArchetype(PlayArchetype):
# Set to True if the entity is a note and contributes to combo and score
# Default is False
is_scored: bool = True
imported_field: int = imported()
exported_field: int = exported()
entity_memory_field: int = entity_memory()
shared_memory_field: int = shared_memory()
@callback(order=1)
def preprocess(self):
...
despawn
property
writable
¶
Whether the entity should be despawned after this frame.
Setting this to True will despawn the entity.
id: int = 0
class-attribute
instance-attribute
¶
The id of the archetype or entity.
If accessed on an entity, always returns the runtime archetype id of the entity, even if it doesn't match the type that was used to access it.
E.g. if an entity of archetype A
is accessed via EntityRef[B]
, the id will
still be the id of A
.
index: int
property
¶
The index of this entity.
is_active: bool
property
¶
Whether this entity is active.
is_despawned: bool
property
¶
Whether this entity is despawned.
is_scored: bool = False
class-attribute
¶
Whether entities of this archetype contribute to combo and score.
is_waiting: bool
property
¶
Whether this entity is waiting to be spawned.
key: int | float = -1
class-attribute
instance-attribute
¶
An optional key for the archetype.
May be useful to identify an archetype in an inheritance hierarchy without needing to check id.
If accessed on an entity, always returns the runtime key of the entity, even if it doesn't match the type that was used to access it.
E.g. if an entity of archetype A
is accessed via EntityRef[B]
, the key
will still be the key of A
.
life: ArchetypeLife
class-attribute
¶
How this entities of this archetype contribute to life depending on judgment.
name: str | None = None
class-attribute
¶
The name of the archetype.
If not set, the name will be the class name.
The name is used in level data.
result: PlayEntityInput
property
¶
The result of this entity.
Only meaningful for scored entities.
derive(name: str, is_scored: bool, key: int | float | None = None) -> type[T]
classmethod
¶
Derive a new archetype class from this archetype.
Roughly equivalent to returning:
class Derived(cls):
name = <name>
is_scored = <is_scored>
key = <key> # Only set if key is not None
This is used to create a new archetype with the same fields and callbacks, but with a different name and whether it is scored. Compared to manually subclassing, this method also enables faster compilation when the same base archetype has multiple derived archetypes by compiling callbacks only once for the base archetype.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name
|
str
|
The name of the new archetype. |
required |
is_scored
|
bool
|
Whether the new archetype is scored. |
required |
key
|
int | float | None
|
A key that can be accessed via the |
None
|
Returns:
Type | Description |
---|---|
type[T]
|
A new archetype class with the same fields and callbacks as this archetype, but with the given name and |
type[T]
|
whether it is scored. |
initialize()
¶
Initialize this entity.
Runs when this entity is spawned.
preprocess()
¶
Perform upfront processing.
Runs first when the level is loaded.
ref() -> EntityRef[Self]
¶
Get a reference to this entity.
Valid both in level data and in callbacks.
should_spawn() -> bool
¶
Return whether the entity should be spawned.
Runs each frame while the entity is the first entity in the spawn queue.
spawn(**kwargs: Any) -> None
classmethod
¶
Spawn an entity of this archetype, injecting the given values into entity memory.
Usage
class MyArchetype(PlayArchetype):
field: int = entity_memory()
def f():
MyArchetype.spawn(field=123)
Parameters:
Name | Type | Description | Default |
---|---|---|---|
**kwargs
|
Any
|
Entity memory values to inject by field name as defined in the Archetype. |
{}
|
spawn_order() -> float
¶
Return the spawn order of the entity.
Runs when the level is loaded after preprocess
.
terminate()
¶
Finalize before despawning.
Runs when the entity is despawned.
touch()
¶
Handle user input.
Runs after update_sequential
each frame.
update_parallel()
¶
Perform parallel actions for this frame.
Runs after touch
each frame.
This is where most gameplay logic should be placed.
update_sequential()
¶
Perform non-parallel actions for this frame.
Runs first each frame.
This is where logic affecting shared memory should be placed.
Other logic should typically be placed in
update_parallel
for better performance.
PreviewArchetype
¶
Bases: _BaseArchetype
Base class for preview mode archetypes.
Usage
class MyArchetype(PreviewArchetype):
imported_field: int = imported()
entity_memory_field: int = entity_memory()
shared_memory_field: int = shared_memory()
@callback(order=1)
def preprocess(self):
...
id: int = 0
class-attribute
instance-attribute
¶
The id of the archetype or entity.
If accessed on an entity, always returns the runtime archetype id of the entity, even if it doesn't match the type that was used to access it.
E.g. if an entity of archetype A
is accessed via EntityRef[B]
, the id will
still be the id of A
.
index: int
property
¶
The index of this entity.
key: int | float = -1
class-attribute
instance-attribute
¶
An optional key for the archetype.
May be useful to identify an archetype in an inheritance hierarchy without needing to check id.
If accessed on an entity, always returns the runtime key of the entity, even if it doesn't match the type that was used to access it.
E.g. if an entity of archetype A
is accessed via EntityRef[B]
, the key
will still be the key of A
.
name: str | None = None
class-attribute
¶
The name of the archetype.
If not set, the name will be the class name.
The name is used in level data.
derive(name: str, is_scored: bool, key: int | float | None = None) -> type[T]
classmethod
¶
Derive a new archetype class from this archetype.
Roughly equivalent to returning:
class Derived(cls):
name = <name>
is_scored = <is_scored>
key = <key> # Only set if key is not None
This is used to create a new archetype with the same fields and callbacks, but with a different name and whether it is scored. Compared to manually subclassing, this method also enables faster compilation when the same base archetype has multiple derived archetypes by compiling callbacks only once for the base archetype.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name
|
str
|
The name of the new archetype. |
required |
is_scored
|
bool
|
Whether the new archetype is scored. |
required |
key
|
int | float | None
|
A key that can be accessed via the |
None
|
Returns:
Type | Description |
---|---|
type[T]
|
A new archetype class with the same fields and callbacks as this archetype, but with the given name and |
type[T]
|
whether it is scored. |
preprocess()
¶
Perform upfront processing.
Runs first when the level is loaded.
ref() -> EntityRef[Self]
¶
Get a reference to this entity.
Valid both in level data and in callbacks.
render()
¶
Render the entity.
Runs after preprocess
.
spawn(**kwargs: Any) -> None
classmethod
¶
Spawn an entity of this archetype, injecting the given values into entity memory.
Usage
class MyArchetype(PlayArchetype):
field: int = entity_memory()
def f():
MyArchetype.spawn(field=123)
Parameters:
Name | Type | Description | Default |
---|---|---|---|
**kwargs
|
Any
|
Entity memory values to inject by field name as defined in the Archetype. |
{}
|
StandardArchetypeName
¶
StandardImport
¶
Standard import annotations for Archetype fields.
Usage
class MyArchetype(WatchArchetype):
judgment: StandardImport.JUDGMENT
ACCURACY = Annotated[float, imported(name='#ACCURACY')]
class-attribute
instance-attribute
¶
The accuracy of the entity.
Automatically supported in watch mode for archetypes with a corresponding scored play mode archetype.
BEAT = Annotated[float, imported(name='#BEAT')]
class-attribute
instance-attribute
¶
The beat of the entity.
BPM = Annotated[float, imported(name='#BPM')]
class-attribute
instance-attribute
¶
The bpm, for bpm change markers.
JUDGMENT = Annotated[int, imported(name='#JUDGMENT')]
class-attribute
instance-attribute
¶
The judgment of the entity.
Automatically supported in watch mode for archetypes with a corresponding scored play mode archetype.
TIMESCALE = Annotated[float, imported(name='#TIMESCALE')]
class-attribute
instance-attribute
¶
The timescale, for timescale change markers.
WatchArchetype
¶
Bases: _BaseArchetype
Base class for watch mode archetypes.
Usage
class MyArchetype(WatchArchetype):
imported_field: int = imported()
entity_memory_field: int = entity_memory()
shared_memory_field: int = shared_memory()
@callback(order=1)
def update_sequential(self):
...
id: int = 0
class-attribute
instance-attribute
¶
The id of the archetype or entity.
If accessed on an entity, always returns the runtime archetype id of the entity, even if it doesn't match the type that was used to access it.
E.g. if an entity of archetype A
is accessed via EntityRef[B]
, the id will
still be the id of A
.
index: int
property
¶
The index of this entity.
is_active: bool
property
¶
Whether this entity is active.
is_scored: bool = False
class-attribute
¶
Whether entities of this archetype contribute to combo and score.
key: int | float = -1
class-attribute
instance-attribute
¶
An optional key for the archetype.
May be useful to identify an archetype in an inheritance hierarchy without needing to check id.
If accessed on an entity, always returns the runtime key of the entity, even if it doesn't match the type that was used to access it.
E.g. if an entity of archetype A
is accessed via EntityRef[B]
, the key
will still be the key of A
.
life: ArchetypeLife
class-attribute
¶
How this entities of this archetype contribute to life depending on judgment.
name: str | None = None
class-attribute
¶
The name of the archetype.
If not set, the name will be the class name.
The name is used in level data.
result: WatchEntityInput
property
¶
The result of this entity.
Only meaningful for scored entities.
derive(name: str, is_scored: bool, key: int | float | None = None) -> type[T]
classmethod
¶
Derive a new archetype class from this archetype.
Roughly equivalent to returning:
class Derived(cls):
name = <name>
is_scored = <is_scored>
key = <key> # Only set if key is not None
This is used to create a new archetype with the same fields and callbacks, but with a different name and whether it is scored. Compared to manually subclassing, this method also enables faster compilation when the same base archetype has multiple derived archetypes by compiling callbacks only once for the base archetype.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name
|
str
|
The name of the new archetype. |
required |
is_scored
|
bool
|
Whether the new archetype is scored. |
required |
key
|
int | float | None
|
A key that can be accessed via the |
None
|
Returns:
Type | Description |
---|---|
type[T]
|
A new archetype class with the same fields and callbacks as this archetype, but with the given name and |
type[T]
|
whether it is scored. |
despawn_time() -> float
¶
Return the despawn time of the entity.
initialize()
¶
Initialize this entity.
Runs when this entity is spawned.
preprocess()
¶
Perform upfront processing.
Runs first when the level is loaded.
ref() -> EntityRef[Self]
¶
Get a reference to this entity.
Valid both in level data and in callbacks.
spawn(**kwargs: Any) -> None
classmethod
¶
Spawn an entity of this archetype, injecting the given values into entity memory.
Usage
class MyArchetype(PlayArchetype):
field: int = entity_memory()
def f():
MyArchetype.spawn(field=123)
Parameters:
Name | Type | Description | Default |
---|---|---|---|
**kwargs
|
Any
|
Entity memory values to inject by field name as defined in the Archetype. |
{}
|
spawn_time() -> float
¶
Return the spawn time of the entity.
terminate()
¶
Finalize before despawning.
Runs when the entity is despawned.
update_parallel()
¶
Parallel update callback.
Runs after touch
each frame.
This is where most gameplay logic should be placed.
update_sequential()
¶
Perform non-parallel actions for this frame.
Runs first each frame.
This is where logic affecting shared memory should be placed.
Other logic should typically be placed in
update_parallel
for better performance.
callback(*, order: int = 0) -> Callable[[T], T]
¶
Annotate a callback with its order.
Callbacks are executed from lowest to highest order. By default, callbacks have an order of 0.
Usage
class MyArchetype(PlayArchetype):
@callback(order=1)
def update_sequential(self):
pass
Parameters:
Name | Type | Description | Default |
---|---|---|---|
order
|
int
|
The order of the callback. Lower values are executed first. |
0
|
entity_data() -> Any
¶
Declare a field as entity data.
Entity data is accessible from other entities, but may only be updated in the
preprocess
callback
and is read-only in other callbacks.
It functions like imported
and shares the same underlying storage,
except that it is not loaded from a level.
Usage
class MyArchetype(PlayArchetype):
field: int = entity_data()
entity_info_at(index: int) -> PlayEntityInfo | WatchEntityInfo | PreviewEntityInfo
¶
Retrieve entity info of the entity at the given index.
Available in play, watch, and preview mode.
entity_memory() -> Any
¶
Declare a field as entity memory.
Entity memory is private to the entity and is not accessible from other entities. It may be read or updated in any callback associated with the entity.
Entity memory fields may also be set when an entity is spawned using the
spawn()
method.
Usage
class MyArchetype(PlayArchetype):
field: int = entity_memory()
exported(*, name: str | None = None) -> Any
¶
Declare a field as exported.
This is only usable in play mode to export data to be loaded in watch mode.
Exported fields are write-only.
Usage
class MyArchetype(PlayArchetype):
field: int = exported()
field_with_explicit_name: int = exported(name="#FIELD")
get_archetype_by_name(name: str) -> AnyArchetype
¶
Return the archetype with the given name in the current mode.
imported(*, name: str | None = None) -> Any
¶
Declare a field as imported.
Imported fields may be loaded from the level.
In watch mode, data may also be loaded from a corresponding exported field in play mode.
Imported fields may only be updated in the preprocess
callback, and are read-only in other callbacks.
Usage
class MyArchetype(PlayArchetype):
field: int = imported()
field_with_explicit_name: int = imported(name="field_name")
shared_memory() -> Any
¶
Declare a field as shared memory.
Shared memory is accessible from other entities.
Shared memory may be read in any callback, but may only be updated by sequential callbacks
(preprocess
,
update_sequential
,
and touch
).
Usage
class MyArchetype(PlayArchetype):
field: int = shared_memory()