mirror of
https://github.com/bombsquad-community/plugin-manager.git
synced 2025-10-08 14:54:36 +00:00
Merge branch 'bombsquad-community:main' into main
This commit is contained in:
commit
4baa419f8a
22 changed files with 4284 additions and 884 deletions
10
README.md
10
README.md
|
|
@ -149,17 +149,17 @@ diff --git a/plugins/utilities/sample_plugin.py b/plugins/utilities/sample_plugi
|
||||||
index ebb7dcc..da2b312 100644
|
index ebb7dcc..da2b312 100644
|
||||||
--- a/plugins/utilities/sample_plugin.py
|
--- a/plugins/utilities/sample_plugin.py
|
||||||
+++ b/plugins/utilities/sample_plugin.py
|
+++ b/plugins/utilities/sample_plugin.py
|
||||||
@@ -5,6 +5,7 @@ import ba
|
@@ -5,6 +5,7 @@ import babase
|
||||||
class Main(ba.Plugin):
|
class Main(babase.Plugin):
|
||||||
def on_app_running(self):
|
def on_app_running(self):
|
||||||
ba.screenmessage("Hi! I am a sample plugin!")
|
babase.screenmessage("Hi! I am a sample plugin!")
|
||||||
|
|
||||||
def has_settings_ui(self):
|
def has_settings_ui(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def show_settings_ui(self, source_widget):
|
def show_settings_ui(self, source_widget):
|
||||||
- ba.screenmessage("You tapped my settings!")
|
- babase.screenmessage("You tapped my settings!")
|
||||||
+ ba.screenmessage("Hey! This is my new screenmessage!")
|
+ babase.screenmessage("Hey! This is my new screenmessage!")
|
||||||
```
|
```
|
||||||
|
|
||||||
To name this new version as `1.1.0`, add `"1.1.0": null,` just above the previous plugin version in `utilities.json`:
|
To name this new version as `1.1.0`, add `"1.1.0": null,` just above the previous plugin version in `utilities.json`:
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,12 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"versions": {
|
"versions": {
|
||||||
|
"2.0.0": {
|
||||||
|
"api_version": 8,
|
||||||
|
"commit_sha": "a941899",
|
||||||
|
"released_on": "20-07-2023",
|
||||||
|
"md5sum": "19f033445a8fe30fc7f4f62d94a54444"
|
||||||
|
},
|
||||||
"1.0.0": {
|
"1.0.0": {
|
||||||
"api_version": 7,
|
"api_version": 7,
|
||||||
"commit_sha": "e59073b",
|
"commit_sha": "e59073b",
|
||||||
|
|
@ -22,6 +28,44 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"icy_emits": {
|
||||||
|
"description": "Survice from icy bombs emitting through cold platform. Playable in teams/ffa/co-op",
|
||||||
|
"external_url": "",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Freaku",
|
||||||
|
"email": "",
|
||||||
|
"discord": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"versions": {
|
||||||
|
"1.0.0": {
|
||||||
|
"api_version": 8,
|
||||||
|
"commit_sha": "48f9302",
|
||||||
|
"released_on": "28-07-2023",
|
||||||
|
"md5sum": "cedc448a3d625065d586445e115fcd1f"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"frozen_one": {
|
||||||
|
"description": "Survive until the timer runs out",
|
||||||
|
"external_url": "",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Freaku",
|
||||||
|
"email": "",
|
||||||
|
"discord": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"versions": {
|
||||||
|
"1.0.0": {
|
||||||
|
"api_version": 8,
|
||||||
|
"commit_sha": "48f9302",
|
||||||
|
"released_on": "28-07-2023",
|
||||||
|
"md5sum": "529c8b9c9a450317d5aa75e8eab47497"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"simon_says": {
|
"simon_says": {
|
||||||
"description": "You better do what Simon says",
|
"description": "You better do what Simon says",
|
||||||
"external_url": "",
|
"external_url": "",
|
||||||
|
|
@ -109,6 +153,12 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"versions": {
|
"versions": {
|
||||||
|
"2.0.0": {
|
||||||
|
"api_version": 8,
|
||||||
|
"commit_sha": "6263872",
|
||||||
|
"released_on": "23-07-2023",
|
||||||
|
"md5sum": "9789ad3583f1d92d4e4b7bc03d09591d"
|
||||||
|
},
|
||||||
"1.0.0": {
|
"1.0.0": {
|
||||||
"api_version": 7,
|
"api_version": 7,
|
||||||
"commit_sha": "2fda676",
|
"commit_sha": "2fda676",
|
||||||
|
|
@ -187,10 +237,16 @@
|
||||||
{
|
{
|
||||||
"name": "Freaku",
|
"name": "Freaku",
|
||||||
"email": "",
|
"email": "",
|
||||||
"discord": "[Just] Freak#4999"
|
"discord": ""
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"versions": {
|
"versions": {
|
||||||
|
"2.0.0": {
|
||||||
|
"api_version": 8,
|
||||||
|
"commit_sha": "48f9302",
|
||||||
|
"released_on": "28-07-2023",
|
||||||
|
"md5sum": "2c457b80b5a35adf0cad1436af4ab3fe"
|
||||||
|
},
|
||||||
"1.1.0": {
|
"1.1.0": {
|
||||||
"api_version": 7,
|
"api_version": 7,
|
||||||
"commit_sha": "0bc9522",
|
"commit_sha": "0bc9522",
|
||||||
|
|
@ -206,10 +262,16 @@
|
||||||
{
|
{
|
||||||
"name": "Freaku",
|
"name": "Freaku",
|
||||||
"email": "",
|
"email": "",
|
||||||
"discord": "[Just] Freak#4999"
|
"discord": ""
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"versions": {
|
"versions": {
|
||||||
|
"2.0.0": {
|
||||||
|
"api_version": 8,
|
||||||
|
"commit_sha": "48f9302",
|
||||||
|
"released_on": "28-07-2023",
|
||||||
|
"md5sum": "49ae645a5afc390ead44d7219b388c78"
|
||||||
|
},
|
||||||
"1.0.0": {
|
"1.0.0": {
|
||||||
"api_version": 7,
|
"api_version": 7,
|
||||||
"commit_sha": "858030b",
|
"commit_sha": "858030b",
|
||||||
|
|
@ -225,10 +287,16 @@
|
||||||
{
|
{
|
||||||
"name": "Freaku",
|
"name": "Freaku",
|
||||||
"email": "",
|
"email": "",
|
||||||
"discord": "[Just] Freak#4999"
|
"discord": ""
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"versions": {
|
"versions": {
|
||||||
|
"2.0.0": {
|
||||||
|
"api_version": 8,
|
||||||
|
"commit_sha": "48f9302",
|
||||||
|
"released_on": "28-07-2023",
|
||||||
|
"md5sum": "4cb6510f9f3ce151720a53a957986864"
|
||||||
|
},
|
||||||
"1.0.0": {
|
"1.0.0": {
|
||||||
"api_version": 7,
|
"api_version": 7,
|
||||||
"commit_sha": "858030b",
|
"commit_sha": "858030b",
|
||||||
|
|
@ -316,6 +384,12 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"versions": {
|
"versions": {
|
||||||
|
"2.0.0": {
|
||||||
|
"api_version": 8,
|
||||||
|
"commit_sha": "f54c993",
|
||||||
|
"released_on": "27-07-2023",
|
||||||
|
"md5sum": "7699483f4c379db809676ac917943d3c"
|
||||||
|
},
|
||||||
"1.0.0": {
|
"1.0.0": {
|
||||||
"api_version": 7,
|
"api_version": 7,
|
||||||
"commit_sha": "2aa1e50",
|
"commit_sha": "2aa1e50",
|
||||||
|
|
@ -412,15 +486,16 @@
|
||||||
{
|
{
|
||||||
"name": "Freaku",
|
"name": "Freaku",
|
||||||
"email": "",
|
"email": "",
|
||||||
"discord": "[Just] Freak#4999"
|
"discord": ""
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "LoupGarou",
|
|
||||||
"email": "LoupGarou5418@outlook.com",
|
|
||||||
"discord": "ʟօʊքɢǟʀօʊ#3063"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"versions": {
|
"versions": {
|
||||||
|
"2.0.0": {
|
||||||
|
"api_version": 8,
|
||||||
|
"commit_sha": "48f9302",
|
||||||
|
"released_on": "28-07-2023",
|
||||||
|
"md5sum": "22b51a147524d84fbc249e61f21ae424"
|
||||||
|
},
|
||||||
"1.1.0": {
|
"1.1.0": {
|
||||||
"api_version": 7,
|
"api_version": 7,
|
||||||
"commit_sha": "2e2540a",
|
"commit_sha": "2e2540a",
|
||||||
|
|
@ -451,6 +526,12 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"versions": {
|
"versions": {
|
||||||
|
"2.0.0": {
|
||||||
|
"api_version": 8,
|
||||||
|
"commit_sha": "e8bbb61",
|
||||||
|
"released_on": "23-07-2023",
|
||||||
|
"md5sum": "1acbeecffada937bdd745f4e4d43f1be"
|
||||||
|
},
|
||||||
"1.0.0": {
|
"1.0.0": {
|
||||||
"api_version": 7,
|
"api_version": 7,
|
||||||
"commit_sha": "7219487",
|
"commit_sha": "7219487",
|
||||||
|
|
@ -470,6 +551,12 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"versions": {
|
"versions": {
|
||||||
|
"2.0.0": {
|
||||||
|
"api_version": 8,
|
||||||
|
"commit_sha": "1a8037e",
|
||||||
|
"released_on": "23-07-2023",
|
||||||
|
"md5sum": "916e37f6e1a8a5be3dd0389ed2c4b261"
|
||||||
|
},
|
||||||
"1.0.0": {
|
"1.0.0": {
|
||||||
"api_version": 7,
|
"api_version": 7,
|
||||||
"commit_sha": "7219487",
|
"commit_sha": "7219487",
|
||||||
|
|
@ -573,6 +660,25 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"quake_original": {
|
||||||
|
"description": "Good ol' Quake minigame",
|
||||||
|
"external_url": "",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Unknown",
|
||||||
|
"email": "",
|
||||||
|
"discord": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"versions": {
|
||||||
|
"1.0.0": {
|
||||||
|
"api_version": 8,
|
||||||
|
"commit_sha": "185480d",
|
||||||
|
"released_on": "24-07-2023",
|
||||||
|
"md5sum": "f68395cc90dc8cddb166a23b2da81b7b"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"ufo_fight": {
|
"ufo_fight": {
|
||||||
"description": "Fight the UFO boss!",
|
"description": "Fight the UFO boss!",
|
||||||
"external_url": "",
|
"external_url": "",
|
||||||
|
|
@ -599,7 +705,7 @@
|
||||||
{
|
{
|
||||||
"name": "Freaku",
|
"name": "Freaku",
|
||||||
"email": "",
|
"email": "",
|
||||||
"discord": "[Just] Freak#4999"
|
"discord": ""
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"versions": {
|
"versions": {
|
||||||
|
|
@ -610,6 +716,87 @@
|
||||||
"md5sum": "197a377652ab0c3bfbe1ca07833924b4"
|
"md5sum": "197a377652ab0c3bfbe1ca07833924b4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"big_ball": {
|
||||||
|
"description": "Score some goals with Big Ball on Football map",
|
||||||
|
"external_url": "",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "MythB",
|
||||||
|
"email": "",
|
||||||
|
"discord": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"versions": {
|
||||||
|
"1.0.0": {
|
||||||
|
"api_version": 8,
|
||||||
|
"commit_sha": "ca3221b",
|
||||||
|
"released_on": "27-07-2023",
|
||||||
|
"md5sum": "39c5b18efd5d5314f30c12fc0bec4931"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"handball": {
|
||||||
|
"description": "Score some goals with handball",
|
||||||
|
"external_url": "",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Unknown",
|
||||||
|
"email": "",
|
||||||
|
"discord": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"versions": {
|
||||||
|
"1.0.0": {
|
||||||
|
"api_version": 8,
|
||||||
|
"commit_sha": "2309aab",
|
||||||
|
"released_on": "24-07-2023",
|
||||||
|
"md5sum": "01b85dc9ef1d464ab604387af09f05dc"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"super_duel": {
|
||||||
|
"description": "Crush your enemy in a 1v1",
|
||||||
|
"external_url": "https://www.youtube.com/watch?v=hvRtiXR-oC0",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "JoseAng3l",
|
||||||
|
"email": "",
|
||||||
|
"discord": "joseang3l"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"versions": {
|
||||||
|
"1.0.0": {
|
||||||
|
"api_version": 8,
|
||||||
|
"commit_sha": "ab26786",
|
||||||
|
"released_on": "27-07-2023",
|
||||||
|
"md5sum": "d0c9c0472d7b145eadf535957a462fdf"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"supersmash": {
|
||||||
|
"description": "Blow up your enemies off the map!",
|
||||||
|
"external_url": "",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Mrmaxmeier",
|
||||||
|
"email": "",
|
||||||
|
"discord": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "JoseAngel",
|
||||||
|
"email": "",
|
||||||
|
"discord": "joseang3l"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"versions": {
|
||||||
|
"1.0.0": {
|
||||||
|
"api_version": 8,
|
||||||
|
"commit_sha": "68e77f2",
|
||||||
|
"released_on": "24-07-2023",
|
||||||
|
"md5sum": "1cbe5b3e85b5dfcee1eb322f33568fd4"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,17 +1,18 @@
|
||||||
# Ported by: Freaku / @[Just] Freak#4999
|
# Ported by your friend: Freaku
|
||||||
|
|
||||||
# Join BCS:
|
# Join BCS:
|
||||||
# https://discord.gg/ucyaesh
|
# https://discord.gg/ucyaesh
|
||||||
|
|
||||||
|
|
||||||
# ba_meta require api 7
|
# ba_meta require api 8
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import ba
|
import babase
|
||||||
from bastd.actor.playerspaz import PlayerSpaz
|
import bascenev1 as bs
|
||||||
|
from bascenev1lib.actor.playerspaz import PlayerSpaz
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any, Type, List, Dict, Tuple, Union, Sequence, Optional
|
from typing import Any, Type, List, Dict, Tuple, Union, Sequence, Optional
|
||||||
|
|
@ -30,8 +31,7 @@ class State:
|
||||||
self.next = None
|
self.next = None
|
||||||
self.index = None
|
self.index = None
|
||||||
|
|
||||||
def apply(self, player, spaz):
|
def apply(self, spaz):
|
||||||
|
|
||||||
spaz.disconnect_controls_from_player()
|
spaz.disconnect_controls_from_player()
|
||||||
spaz.connect_controls_to_player(enable_punch=self.punch,
|
spaz.connect_controls_to_player(enable_punch=self.punch,
|
||||||
enable_bomb=self.bomb,
|
enable_bomb=self.bomb,
|
||||||
|
|
@ -43,18 +43,6 @@ class State:
|
||||||
spaz.bomb_type = self.bomb
|
spaz.bomb_type = self.bomb
|
||||||
spaz.set_score_text(self.name)
|
spaz.set_score_text(self.name)
|
||||||
|
|
||||||
def set_controls():
|
|
||||||
player.actor.node.bomb_pressed = True
|
|
||||||
player.actor.on_bomb_release()
|
|
||||||
|
|
||||||
release_input = (ba.InputType.PUNCH_RELEASE, ba.InputType.PICK_UP_RELEASE)
|
|
||||||
if not self.bomb is None:
|
|
||||||
for release in release_input:
|
|
||||||
player.assigninput(
|
|
||||||
release,
|
|
||||||
set_controls
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_setting(self):
|
def get_setting(self):
|
||||||
return (self.name)
|
return (self.name)
|
||||||
|
|
||||||
|
|
@ -68,22 +56,22 @@ states = [State(bomb='normal', name='Basic Bombs'),
|
||||||
State(curse=True, name='Cursed', final=True)]
|
State(curse=True, name='Cursed', final=True)]
|
||||||
|
|
||||||
|
|
||||||
class Player(ba.Player['Team']):
|
class Player(bs.Player['Team']):
|
||||||
"""Our player type for this game."""
|
"""Our player type for this game."""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.state = None
|
self.state = None
|
||||||
|
|
||||||
|
|
||||||
class Team(ba.Team[Player]):
|
class Team(bs.Team[Player]):
|
||||||
"""Our team type for this game."""
|
"""Our team type for this game."""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.score = 0
|
self.score = 0
|
||||||
|
|
||||||
|
|
||||||
# ba_meta export game
|
# ba_meta export bascenev1.GameActivity
|
||||||
class ArmsRaceGame(ba.TeamGameActivity[Player, Team]):
|
class ArmsRaceGame(bs.TeamGameActivity[Player, Team]):
|
||||||
"""A game type based on acquiring kills."""
|
"""A game type based on acquiring kills."""
|
||||||
|
|
||||||
name = 'Arms Race'
|
name = 'Arms Race'
|
||||||
|
|
@ -94,9 +82,9 @@ class ArmsRaceGame(ba.TeamGameActivity[Player, Team]):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_available_settings(
|
def get_available_settings(
|
||||||
cls, sessiontype: Type[ba.Session]) -> List[ba.Setting]:
|
cls, sessiontype: Type[bs.Session]) -> List[babase.Setting]:
|
||||||
settings = [
|
settings = [
|
||||||
ba.IntChoiceSetting(
|
bs.IntChoiceSetting(
|
||||||
'Time Limit',
|
'Time Limit',
|
||||||
choices=[
|
choices=[
|
||||||
('None', 0),
|
('None', 0),
|
||||||
|
|
@ -108,7 +96,7 @@ class ArmsRaceGame(ba.TeamGameActivity[Player, Team]):
|
||||||
],
|
],
|
||||||
default=0,
|
default=0,
|
||||||
),
|
),
|
||||||
ba.FloatChoiceSetting(
|
bs.FloatChoiceSetting(
|
||||||
'Respawn Times',
|
'Respawn Times',
|
||||||
choices=[
|
choices=[
|
||||||
('Shorter', 0.25),
|
('Shorter', 0.25),
|
||||||
|
|
@ -119,21 +107,21 @@ class ArmsRaceGame(ba.TeamGameActivity[Player, Team]):
|
||||||
],
|
],
|
||||||
default=1.0,
|
default=1.0,
|
||||||
),
|
),
|
||||||
ba.BoolSetting('Epic Mode', default=False)]
|
bs.BoolSetting('Epic Mode', default=False)]
|
||||||
for state in states:
|
for state in states:
|
||||||
if not state.required:
|
if not state.required:
|
||||||
settings.append(ba.BoolSetting(state.get_setting(), default=True))
|
settings.append(bs.BoolSetting(state.get_setting(), default=True))
|
||||||
|
|
||||||
return settings
|
return settings
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
|
def supports_session_type(cls, sessiontype: Type[bs.Session]) -> bool:
|
||||||
return (issubclass(sessiontype, ba.DualTeamSession)
|
return (issubclass(sessiontype, bs.DualTeamSession)
|
||||||
or issubclass(sessiontype, ba.FreeForAllSession))
|
or issubclass(sessiontype, bs.FreeForAllSession))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
|
def get_supported_maps(cls, sessiontype: Type[bs.Session]) -> List[str]:
|
||||||
return ba.getmaps('melee')
|
return bs.app.classic.getmaps('melee')
|
||||||
|
|
||||||
def __init__(self, settings: dict):
|
def __init__(self, settings: dict):
|
||||||
super().__init__(settings)
|
super().__init__(settings)
|
||||||
|
|
@ -142,14 +130,14 @@ class ArmsRaceGame(ba.TeamGameActivity[Player, Team]):
|
||||||
if i < len(self.states) and not state.final:
|
if i < len(self.states) and not state.final:
|
||||||
state.next = self.states[i + 1]
|
state.next = self.states[i + 1]
|
||||||
state.index = i
|
state.index = i
|
||||||
self._dingsound = ba.getsound('dingSmall')
|
self._dingsound = bs.getsound('dingSmall')
|
||||||
self._epic_mode = bool(settings['Epic Mode'])
|
self._epic_mode = bool(settings['Epic Mode'])
|
||||||
self._time_limit = float(settings['Time Limit'])
|
self._time_limit = float(settings['Time Limit'])
|
||||||
|
|
||||||
# Base class overrides.
|
# Base class overrides.
|
||||||
self.slow_motion = self._epic_mode
|
self.slow_motion = self._epic_mode
|
||||||
self.default_music = (ba.MusicType.EPIC if self._epic_mode else
|
self.default_music = (bs.MusicType.EPIC if self._epic_mode else
|
||||||
ba.MusicType.TO_THE_DEATH)
|
bs.MusicType.TO_THE_DEATH)
|
||||||
|
|
||||||
def get_instance_description(self) -> Union[str, Sequence]:
|
def get_instance_description(self) -> Union[str, Sequence]:
|
||||||
return 'Upgrade your weapon by eliminating enemies.'
|
return 'Upgrade your weapon by eliminating enemies.'
|
||||||
|
|
@ -168,12 +156,11 @@ class ArmsRaceGame(ba.TeamGameActivity[Player, Team]):
|
||||||
self.spawn_player(player)
|
self.spawn_player(player)
|
||||||
|
|
||||||
# overriding the default character spawning..
|
# overriding the default character spawning..
|
||||||
|
|
||||||
def spawn_player(self, player):
|
def spawn_player(self, player):
|
||||||
if player.state is None:
|
if player.state is None:
|
||||||
player.state = self.states[0]
|
player.state = self.states[0]
|
||||||
super().spawn_player(player)
|
super().spawn_player(player)
|
||||||
player.state.apply(player, player.actor)
|
player.state.apply(player.actor)
|
||||||
|
|
||||||
def isValidKill(self, m):
|
def isValidKill(self, m):
|
||||||
if m.getkillerplayer(Player) is None:
|
if m.getkillerplayer(Player) is None:
|
||||||
|
|
@ -186,13 +173,12 @@ class ArmsRaceGame(ba.TeamGameActivity[Player, Team]):
|
||||||
|
|
||||||
def handlemessage(self, msg: Any) -> Any:
|
def handlemessage(self, msg: Any) -> Any:
|
||||||
|
|
||||||
if isinstance(msg, ba.PlayerDiedMessage):
|
if isinstance(msg, bs.PlayerDiedMessage):
|
||||||
if self.isValidKill(msg):
|
if self.isValidKill(msg):
|
||||||
self.stats.player_scored(msg.getkillerplayer(Player), 10, kill=True)
|
self.stats.player_scored(msg.getkillerplayer(Player), 10, kill=True)
|
||||||
if not msg.getkillerplayer(Player).state.final:
|
if not msg.getkillerplayer(Player).state.final:
|
||||||
msg.getkillerplayer(Player).state = msg.getkillerplayer(Player).state.next
|
msg.getkillerplayer(Player).state = msg.getkillerplayer(Player).state.next
|
||||||
msg.getkillerplayer(Player).state.apply(
|
msg.getkillerplayer(Player).state.apply(msg.getkillerplayer(Player).actor)
|
||||||
msg.getkillerplayer(Player), msg.getkillerplayer(Player).actor)
|
|
||||||
else:
|
else:
|
||||||
msg.getkillerplayer(Player).team.score += 1
|
msg.getkillerplayer(Player).team.score += 1
|
||||||
self.end_game()
|
self.end_game()
|
||||||
|
|
@ -203,7 +189,7 @@ class ArmsRaceGame(ba.TeamGameActivity[Player, Team]):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def end_game(self) -> None:
|
def end_game(self) -> None:
|
||||||
results = ba.GameResults()
|
results = bs.GameResults()
|
||||||
for team in self.teams:
|
for team in self.teams:
|
||||||
results.set_team_score(team, team.score)
|
results.set_team_score(team, team.score)
|
||||||
self.end(results=results)
|
self.end(results=results)
|
||||||
|
|
|
||||||
524
plugins/minigames/big_ball.py
Normal file
524
plugins/minigames/big_ball.py
Normal file
|
|
@ -0,0 +1,524 @@
|
||||||
|
# Made by MythB
|
||||||
|
# Ported by: MysteriousBoi
|
||||||
|
|
||||||
|
|
||||||
|
# ba_meta require api 8
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
import babase
|
||||||
|
import bauiv1 as bui
|
||||||
|
import bascenev1 as bs
|
||||||
|
import random
|
||||||
|
from bascenev1lib.actor.playerspaz import PlayerSpaz
|
||||||
|
from bascenev1lib.actor.scoreboard import Scoreboard
|
||||||
|
from bascenev1lib.actor.powerupbox import PowerupBoxFactory
|
||||||
|
from bascenev1lib.gameutils import SharedObjects
|
||||||
|
from bascenev1lib.actor.flag import Flag
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from typing import Any, Sequence, Dict, Type, List, Optional, Union
|
||||||
|
|
||||||
|
|
||||||
|
class PuckDiedMessage:
|
||||||
|
"""Inform something that a puck has died."""
|
||||||
|
|
||||||
|
def __init__(self, puck: Puck):
|
||||||
|
self.puck = puck
|
||||||
|
|
||||||
|
# goalpost
|
||||||
|
|
||||||
|
|
||||||
|
class FlagKale(bs.Actor):
|
||||||
|
def __init__(self, position=(0, 2.5, 0), color=(1, 1, 1)):
|
||||||
|
super().__init__()
|
||||||
|
activity = self.getactivity()
|
||||||
|
shared = SharedObjects.get()
|
||||||
|
self.node = bs.newnode('flag',
|
||||||
|
attrs={'position': (position[0], position[1]+0.75, position[2]),
|
||||||
|
'color_texture': activity._flagKaleTex,
|
||||||
|
'color': color,
|
||||||
|
'materials': [shared.object_material, activity._kaleMaterial],
|
||||||
|
},
|
||||||
|
delegate=self)
|
||||||
|
|
||||||
|
def handleMessage(self, m):
|
||||||
|
if isinstance(m, bs.DieMessage):
|
||||||
|
if self.node.exists():
|
||||||
|
self.node.delete()
|
||||||
|
elif isinstance(m, bs.OutOfBoundsMessage):
|
||||||
|
self.handlemessage(bs.DieMessage())
|
||||||
|
else:
|
||||||
|
super().handlemessage(msg)
|
||||||
|
|
||||||
|
|
||||||
|
class Puck(bs.Actor):
|
||||||
|
def __init__(self, position: Sequence[float] = (0.0, 1.0, 0.0)):
|
||||||
|
super().__init__()
|
||||||
|
shared = SharedObjects.get()
|
||||||
|
activity = self.getactivity()
|
||||||
|
|
||||||
|
# Spawn just above the provided point.
|
||||||
|
self._spawn_pos = (position[0], position[1] + 1.0, position[2])
|
||||||
|
self.last_players_to_touch: Dict[int, Player] = {}
|
||||||
|
self.scored = False
|
||||||
|
assert activity is not None
|
||||||
|
assert isinstance(activity, BBGame)
|
||||||
|
pmats = [shared.object_material, activity.puck_material]
|
||||||
|
self.node = bs.newnode('prop',
|
||||||
|
delegate=self,
|
||||||
|
attrs={
|
||||||
|
'mesh': activity._ballModel,
|
||||||
|
'color_texture': activity._ballTex,
|
||||||
|
'body': 'sphere',
|
||||||
|
'reflection': 'soft',
|
||||||
|
'reflection_scale': [0.2],
|
||||||
|
'shadow_size': 0.8,
|
||||||
|
'is_area_of_interest': True,
|
||||||
|
'position': self._spawn_pos,
|
||||||
|
'materials': pmats,
|
||||||
|
'body_scale': 4,
|
||||||
|
'mesh_scale': 1,
|
||||||
|
'density': 0.02})
|
||||||
|
bs.animate(self.node, 'mesh_scale', {0: 0, 0.2: 1.3, 0.26: 1})
|
||||||
|
|
||||||
|
def handlemessage(self, msg: Any) -> Any:
|
||||||
|
if isinstance(msg, bs.DieMessage):
|
||||||
|
assert self.node
|
||||||
|
self.node.delete()
|
||||||
|
activity = self._activity()
|
||||||
|
if activity and not msg.immediate:
|
||||||
|
activity.handlemessage(PuckDiedMessage(self))
|
||||||
|
|
||||||
|
# If we go out of bounds, move back to where we started.
|
||||||
|
elif isinstance(msg, bs.OutOfBoundsMessage):
|
||||||
|
assert self.node
|
||||||
|
self.node.position = self._spawn_pos
|
||||||
|
|
||||||
|
elif isinstance(msg, bs.HitMessage):
|
||||||
|
assert self.node
|
||||||
|
assert msg.force_direction is not None
|
||||||
|
self.node.handlemessage(
|
||||||
|
'impulse', msg.pos[0], msg.pos[1], msg.pos[2], msg.velocity[0],
|
||||||
|
msg.velocity[1], msg.velocity[2], 1.0 * msg.magnitude,
|
||||||
|
1.0 * msg.velocity_magnitude, msg.radius, 0,
|
||||||
|
msg.force_direction[0], msg.force_direction[1],
|
||||||
|
msg.force_direction[2])
|
||||||
|
|
||||||
|
# If this hit came from a player, log them as the last to touch us.
|
||||||
|
s_player = msg.get_source_player(Player)
|
||||||
|
if s_player is not None:
|
||||||
|
activity = self._activity()
|
||||||
|
if activity:
|
||||||
|
if s_player in activity.players:
|
||||||
|
self.last_players_to_touch[s_player.team.id] = s_player
|
||||||
|
else:
|
||||||
|
super().handlemessage(msg)
|
||||||
|
|
||||||
|
# for night mode: using a actor with large shadow and little mesh scale. Better then tint i think, players and objects more visible
|
||||||
|
|
||||||
|
|
||||||
|
class NightMod(bs.Actor):
|
||||||
|
def __init__(self, position=(0, 0, 0)):
|
||||||
|
super().__init__()
|
||||||
|
shared = SharedObjects.get()
|
||||||
|
activity = self.getactivity()
|
||||||
|
# spawn just above the provided point
|
||||||
|
self._spawnPos = (position[0], position[1], position[2])
|
||||||
|
self.node = bs.newnode("prop",
|
||||||
|
attrs={'mesh': activity._nightModel,
|
||||||
|
'color_texture': activity._nightTex,
|
||||||
|
'body': 'sphere',
|
||||||
|
'reflection': 'soft',
|
||||||
|
'body_scale': 0.1,
|
||||||
|
'mesh_scale': 0.001,
|
||||||
|
'density': 0.010,
|
||||||
|
'reflection_scale': [0.23],
|
||||||
|
'shadow_size': 999999.0,
|
||||||
|
'is_area_of_interest': True,
|
||||||
|
'position': self._spawnPos,
|
||||||
|
'materials': [activity._nightMaterial]
|
||||||
|
},
|
||||||
|
delegate=self)
|
||||||
|
|
||||||
|
def handlemssage(self, m):
|
||||||
|
super().handlemessage(m)
|
||||||
|
|
||||||
|
|
||||||
|
class Player(bs.Player['Team']):
|
||||||
|
"""Our player type for this game."""
|
||||||
|
|
||||||
|
|
||||||
|
class Team(bs.Team[Player]):
|
||||||
|
"""Our team type for this game."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.score = 0
|
||||||
|
|
||||||
|
|
||||||
|
# ba_meta export bascenev1.GameActivity
|
||||||
|
class BBGame(bs.TeamGameActivity[Player, Team]):
|
||||||
|
name = 'Big Ball'
|
||||||
|
description = 'Score some goals.\nFlags are goalposts.\nScored team players get boxing gloves,\nNon-scored team players getting shield (if Grant Powers on Score).\nYou can also set Night Mode!'
|
||||||
|
available_settings = [
|
||||||
|
bs.IntSetting(
|
||||||
|
'Score to Win',
|
||||||
|
min_value=1,
|
||||||
|
default=1,
|
||||||
|
increment=1,
|
||||||
|
),
|
||||||
|
bs.IntChoiceSetting(
|
||||||
|
'Time Limit',
|
||||||
|
choices=[
|
||||||
|
('None', 0),
|
||||||
|
('1 Minute', 60),
|
||||||
|
('2 Minutes', 120),
|
||||||
|
('5 Minutes', 300),
|
||||||
|
('10 Minutes', 600),
|
||||||
|
('20 Minutes', 1200),
|
||||||
|
],
|
||||||
|
default=0,
|
||||||
|
),
|
||||||
|
bs.FloatChoiceSetting(
|
||||||
|
'Respawn Times',
|
||||||
|
choices=[
|
||||||
|
('Shorter', 0.25),
|
||||||
|
('Short', 0.5),
|
||||||
|
('Normal', 1.0),
|
||||||
|
('Long', 2.0),
|
||||||
|
('Longer', 4.0),
|
||||||
|
],
|
||||||
|
default=1.0,
|
||||||
|
),
|
||||||
|
bs.BoolSetting('Epic Mode', True),
|
||||||
|
bs.BoolSetting('Night Mode', False),
|
||||||
|
bs.BoolSetting('Grant Powers on Score', False)
|
||||||
|
]
|
||||||
|
default_music = bs.MusicType.HOCKEY
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def supports_session_type(cls, sessiontype: Type[bs.Session]) -> bool:
|
||||||
|
return issubclass(sessiontype, bs.DualTeamSession)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_supported_maps(cls, sessiontype: Type[bs.Session]) -> List[str]:
|
||||||
|
return ['Football Stadium']
|
||||||
|
|
||||||
|
def __init__(self, settings: dict):
|
||||||
|
super().__init__(settings)
|
||||||
|
shared = SharedObjects.get()
|
||||||
|
self._scoreboard = Scoreboard()
|
||||||
|
self._cheer_sound = bs.getsound('cheer')
|
||||||
|
self._chant_sound = bs.getsound('crowdChant')
|
||||||
|
self._foghorn_sound = bs.getsound('foghorn')
|
||||||
|
self._swipsound = bs.getsound('swip')
|
||||||
|
self._whistle_sound = bs.getsound('refWhistle')
|
||||||
|
self._ballModel = bs.getmesh("shield")
|
||||||
|
self._ballTex = bs.gettexture("eggTex1")
|
||||||
|
self._ballSound = bs.getsound("impactMedium2")
|
||||||
|
self._flagKaleTex = bs.gettexture("star")
|
||||||
|
self._kaleSound = bs.getsound("metalHit")
|
||||||
|
self._nightModel = bs.getmesh("shield")
|
||||||
|
self._nightTex = bs.gettexture("black")
|
||||||
|
self._kaleMaterial = bs.Material()
|
||||||
|
# add friction to flags for standing our position (as far as)
|
||||||
|
self._kaleMaterial.add_actions(conditions=("they_have_material", shared.footing_material),
|
||||||
|
actions=(("modify_part_collision", "friction", 9999.5)))
|
||||||
|
self._kaleMaterial.add_actions(conditions=(("we_are_younger_than", 1), 'and',
|
||||||
|
("they_have_material", shared.object_material)),
|
||||||
|
actions=(("modify_part_collision", "collide", False)))
|
||||||
|
self._kaleMaterial.add_actions(conditions=("they_have_material", shared.pickup_material),
|
||||||
|
actions=(("modify_part_collision", "collide", False)))
|
||||||
|
self._kaleMaterial.add_actions(
|
||||||
|
conditions=('they_have_material', shared.object_material),
|
||||||
|
actions=(('impact_sound', self._kaleSound, 2, 5)))
|
||||||
|
# we dont wanna hit the night so
|
||||||
|
self._nightMaterial = bs.Material()
|
||||||
|
self._nightMaterial.add_actions(conditions=(('they_have_material', shared.pickup_material), 'or',
|
||||||
|
('they_have_material', shared.attack_material)),
|
||||||
|
actions=(('modify_part_collision', 'collide', False)))
|
||||||
|
# we also dont want anything moving it
|
||||||
|
self._nightMaterial.add_actions(
|
||||||
|
conditions=(('they_have_material', shared.object_material), 'or',
|
||||||
|
('they_dont_have_material', shared.footing_material)),
|
||||||
|
actions=(('modify_part_collision', 'collide', False),
|
||||||
|
('modify_part_collision', 'physical', False)))
|
||||||
|
self.puck_material = bs.Material()
|
||||||
|
self.puck_material.add_actions(actions=(('modify_part_collision',
|
||||||
|
'friction', 0.5)))
|
||||||
|
self.puck_material.add_actions(conditions=('they_have_material',
|
||||||
|
shared.pickup_material),
|
||||||
|
actions=('modify_part_collision',
|
||||||
|
'collide', False))
|
||||||
|
self.puck_material.add_actions(
|
||||||
|
conditions=(
|
||||||
|
('we_are_younger_than', 100),
|
||||||
|
'and',
|
||||||
|
('they_have_material', shared.object_material),
|
||||||
|
),
|
||||||
|
actions=('modify_node_collision', 'collide', False),
|
||||||
|
)
|
||||||
|
self.puck_material.add_actions(conditions=('they_have_material',
|
||||||
|
shared.footing_material),
|
||||||
|
actions=('impact_sound',
|
||||||
|
self._ballSound, 0.2, 5))
|
||||||
|
|
||||||
|
# Keep track of which player last touched the puck
|
||||||
|
self.puck_material.add_actions(
|
||||||
|
conditions=('they_have_material', shared.player_material),
|
||||||
|
actions=(('call', 'at_connect',
|
||||||
|
self._handle_puck_player_collide), ))
|
||||||
|
|
||||||
|
# We want the puck to kill powerups; not get stopped by them
|
||||||
|
self.puck_material.add_actions(
|
||||||
|
conditions=('they_have_material',
|
||||||
|
PowerupBoxFactory.get().powerup_material),
|
||||||
|
actions=(('modify_part_collision', 'physical', False),
|
||||||
|
('message', 'their_node', 'at_connect', bs.DieMessage())))
|
||||||
|
self._score_region_material = bs.Material()
|
||||||
|
self._score_region_material.add_actions(
|
||||||
|
conditions=('they_have_material', self.puck_material),
|
||||||
|
actions=(('modify_part_collision', 'collide',
|
||||||
|
True), ('modify_part_collision', 'physical', False),
|
||||||
|
('call', 'at_connect', self._handle_score)))
|
||||||
|
self._puck_spawn_pos: Optional[Sequence[float]] = None
|
||||||
|
self._score_regions: Optional[List[bs.NodeActor]] = None
|
||||||
|
self._puck: Optional[Puck] = None
|
||||||
|
self._score_to_win = int(settings['Score to Win'])
|
||||||
|
self._time_limit = float(settings['Time Limit'])
|
||||||
|
self._nm = bool(settings['Night Mode'])
|
||||||
|
self._grant_power = bool(settings['Grant Powers on Score'])
|
||||||
|
self._epic_mode = bool(settings['Epic Mode'])
|
||||||
|
# Base class overrides.
|
||||||
|
self.slow_motion = self._epic_mode
|
||||||
|
|
||||||
|
def get_instance_description(self) -> Union[str, Sequence]:
|
||||||
|
if self._score_to_win == 1:
|
||||||
|
return 'Score a goal.'
|
||||||
|
return 'Score ${ARG1} goals.', self._score_to_win
|
||||||
|
|
||||||
|
def get_instance_description_short(self) -> Union[str, Sequence]:
|
||||||
|
if self._score_to_win == 1:
|
||||||
|
return 'score a goal'
|
||||||
|
return 'score ${ARG1} goals', self._score_to_win
|
||||||
|
|
||||||
|
def on_begin(self) -> None:
|
||||||
|
super().on_begin()
|
||||||
|
|
||||||
|
self.setup_standard_time_limit(self._time_limit)
|
||||||
|
self.setup_standard_powerup_drops()
|
||||||
|
self._puck_spawn_pos = self.map.get_flag_position(None)
|
||||||
|
self._spawn_puck()
|
||||||
|
# for night mode we need night actor. And same goodies for nigh mode
|
||||||
|
if self._nm:
|
||||||
|
self._nightSpawny(), self._flagKaleFlash()
|
||||||
|
|
||||||
|
# Set up the two score regions.
|
||||||
|
defs = self.map.defs
|
||||||
|
self._score_regions = []
|
||||||
|
self._score_regions.append(
|
||||||
|
bs.NodeActor(
|
||||||
|
bs.newnode('region',
|
||||||
|
attrs={
|
||||||
|
'position': (13.75, 0.85744967453, 0.1095578275),
|
||||||
|
'scale': (1.05, 1.1, 3.8),
|
||||||
|
'type': 'box',
|
||||||
|
'materials': [self._score_region_material]
|
||||||
|
})))
|
||||||
|
self._score_regions.append(
|
||||||
|
bs.NodeActor(
|
||||||
|
bs.newnode('region',
|
||||||
|
attrs={
|
||||||
|
'position': (-13.55, 0.85744967453, 0.1095578275),
|
||||||
|
'scale': (1.05, 1.1, 3.8),
|
||||||
|
'type': 'box',
|
||||||
|
'materials': [self._score_region_material]
|
||||||
|
})))
|
||||||
|
self._update_scoreboard()
|
||||||
|
self._chant_sound.play()
|
||||||
|
|
||||||
|
def _nightSpawny(self):
|
||||||
|
self.MythBrk = NightMod(position=(0, 0.05744967453, 0))
|
||||||
|
|
||||||
|
# spawn some goodies on nightmode for pretty visuals
|
||||||
|
def _flagKaleFlash(self):
|
||||||
|
# flags positions
|
||||||
|
kale1 = (-12.45, 0.05744967453, -2.075)
|
||||||
|
kale2 = (-12.45, 0.05744967453, 2.075)
|
||||||
|
kale3 = (12.66, 0.03986567039, 2.075)
|
||||||
|
kale4 = (12.66, 0.03986567039, -2.075)
|
||||||
|
|
||||||
|
flash = bs.newnode("light",
|
||||||
|
attrs={'position': kale1,
|
||||||
|
'radius': 0.15,
|
||||||
|
'color': (1.0, 1.0, 0.7)})
|
||||||
|
|
||||||
|
flash = bs.newnode("light",
|
||||||
|
attrs={'position': kale2,
|
||||||
|
'radius': 0.15,
|
||||||
|
'color': (1.0, 1.0, 0.7)})
|
||||||
|
|
||||||
|
flash = bs.newnode("light",
|
||||||
|
attrs={'position': kale3,
|
||||||
|
'radius': 0.15,
|
||||||
|
'color': (0.7, 1.0, 1.0)})
|
||||||
|
|
||||||
|
flash = bs.newnode("light",
|
||||||
|
attrs={'position': kale4,
|
||||||
|
'radius': 0.15,
|
||||||
|
'color': (0.7, 1.0, 1.0)})
|
||||||
|
# flags positions
|
||||||
|
|
||||||
|
def _flagKalesSpawn(self):
|
||||||
|
for team in self.teams:
|
||||||
|
if team.id == 0:
|
||||||
|
_colorTeam0 = team.color
|
||||||
|
if team.id == 1:
|
||||||
|
_colorTeam1 = team.color
|
||||||
|
|
||||||
|
self._MythB = FlagKale(position=(-12.45, 0.05744967453, -2.075), color=_colorTeam0)
|
||||||
|
self._MythB2 = FlagKale(position=(-12.45, 0.05744967453, 2.075), color=_colorTeam0)
|
||||||
|
self._MythB3 = FlagKale(position=(12.66, 0.03986567039, 2.075), color=_colorTeam1)
|
||||||
|
self._MythB4 = FlagKale(position=(12.66, 0.03986567039, -2.075), color=_colorTeam1)
|
||||||
|
|
||||||
|
def on_team_join(self, team: Team) -> None:
|
||||||
|
self._update_scoreboard()
|
||||||
|
|
||||||
|
def _handle_puck_player_collide(self) -> None:
|
||||||
|
collision = bs.getcollision()
|
||||||
|
try:
|
||||||
|
puck = collision.sourcenode.getdelegate(Puck, True)
|
||||||
|
player = collision.opposingnode.getdelegate(PlayerSpaz,
|
||||||
|
True).getplayer(
|
||||||
|
Player, True)
|
||||||
|
except bs.NotFoundError:
|
||||||
|
return
|
||||||
|
|
||||||
|
puck.last_players_to_touch[player.team.id] = player
|
||||||
|
|
||||||
|
def _kill_puck(self) -> None:
|
||||||
|
self._puck = None
|
||||||
|
|
||||||
|
def _handle_score(self) -> None:
|
||||||
|
"""A point has been scored."""
|
||||||
|
|
||||||
|
assert self._puck is not None
|
||||||
|
assert self._score_regions is not None
|
||||||
|
|
||||||
|
# Our puck might stick around for a second or two
|
||||||
|
# we don't want it to be able to score again.
|
||||||
|
if self._puck.scored:
|
||||||
|
return
|
||||||
|
|
||||||
|
region = bs.getcollision().sourcenode
|
||||||
|
index = 0
|
||||||
|
for index in range(len(self._score_regions)):
|
||||||
|
if region == self._score_regions[index].node:
|
||||||
|
break
|
||||||
|
|
||||||
|
for team in self.teams:
|
||||||
|
if team.id == index:
|
||||||
|
scoring_team = team
|
||||||
|
team.score += 1
|
||||||
|
|
||||||
|
# tell scored team players to celebrate and give them to boxing gloves
|
||||||
|
if self._grant_power:
|
||||||
|
for player in team.players:
|
||||||
|
try:
|
||||||
|
player.actor.node.handlemessage(bs.PowerupMessage('punch'))
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Tell all players to celebrate.
|
||||||
|
for player in team.players:
|
||||||
|
if player.actor:
|
||||||
|
player.actor.handlemessage(bs.CelebrateMessage(2.0))
|
||||||
|
|
||||||
|
# If we've got the player from the scoring team that last
|
||||||
|
# touched us, give them points.
|
||||||
|
if (scoring_team.id in self._puck.last_players_to_touch
|
||||||
|
and self._puck.last_players_to_touch[scoring_team.id]):
|
||||||
|
self.stats.player_scored(
|
||||||
|
self._puck.last_players_to_touch[scoring_team.id],
|
||||||
|
100,
|
||||||
|
big_message=True)
|
||||||
|
|
||||||
|
# End game if we won.
|
||||||
|
if team.score >= self._score_to_win:
|
||||||
|
self.end_game()
|
||||||
|
else:
|
||||||
|
if self._grant_power:
|
||||||
|
for player in team.players:
|
||||||
|
try:
|
||||||
|
player.actor.node.handlemessage(bs.PowerupMessage('shield'))
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
self._foghorn_sound.play()
|
||||||
|
self._cheer_sound.play()
|
||||||
|
|
||||||
|
self._puck.scored = True
|
||||||
|
|
||||||
|
# Kill the puck (it'll respawn itself shortly).
|
||||||
|
bs.timer(1.0, self._kill_puck)
|
||||||
|
|
||||||
|
light = bs.newnode('light',
|
||||||
|
attrs={
|
||||||
|
'position': bs.getcollision().position,
|
||||||
|
'height_attenuated': False,
|
||||||
|
'color': (1, 0, 0)
|
||||||
|
})
|
||||||
|
bs.animate(light, 'intensity', {0: 0, 0.5: 1, 1.0: 0}, loop=True)
|
||||||
|
bs.timer(1.0, light.delete)
|
||||||
|
|
||||||
|
bs.cameraflash(duration=10.0)
|
||||||
|
self._update_scoreboard()
|
||||||
|
|
||||||
|
def end_game(self) -> None:
|
||||||
|
results = bs.GameResults()
|
||||||
|
for team in self.teams:
|
||||||
|
results.set_team_score(team, team.score)
|
||||||
|
self.end(results=results)
|
||||||
|
|
||||||
|
def _update_scoreboard(self) -> None:
|
||||||
|
winscore = self._score_to_win
|
||||||
|
for team in self.teams:
|
||||||
|
self._scoreboard.set_team_value(team, team.score, winscore)
|
||||||
|
|
||||||
|
def handlemessage(self, msg: Any) -> Any:
|
||||||
|
|
||||||
|
# Respawn dead players if they're still in the game.
|
||||||
|
if isinstance(msg, bs.PlayerDiedMessage):
|
||||||
|
# Augment standard behavior...
|
||||||
|
super().handlemessage(msg)
|
||||||
|
self.respawn_player(msg.getplayer(Player))
|
||||||
|
|
||||||
|
# Respawn dead pucks.
|
||||||
|
elif isinstance(msg, PuckDiedMessage):
|
||||||
|
if not self.has_ended():
|
||||||
|
bs.timer(3.0, self._spawn_puck)
|
||||||
|
else:
|
||||||
|
super().handlemessage(msg)
|
||||||
|
|
||||||
|
def _flash_puck_spawn(self) -> None:
|
||||||
|
light = bs.newnode('light',
|
||||||
|
attrs={
|
||||||
|
'position': self._puck_spawn_pos,
|
||||||
|
'height_attenuated': False,
|
||||||
|
'color': (1, 0, 0)
|
||||||
|
})
|
||||||
|
bs.animate(light, 'intensity', {0.0: 0, 0.25: 1, 0.5: 0}, loop=True)
|
||||||
|
bs.timer(1.0, light.delete)
|
||||||
|
|
||||||
|
def _spawn_puck(self) -> None:
|
||||||
|
self._swipsound.play()
|
||||||
|
self._whistle_sound.play()
|
||||||
|
self._flagKalesSpawn()
|
||||||
|
self._flash_puck_spawn()
|
||||||
|
assert self._puck_spawn_pos is not None
|
||||||
|
self._puck = Puck(position=self._puck_spawn_pos)
|
||||||
|
self._puck.light = bs.newnode('light',
|
||||||
|
owner=self._puck.node,
|
||||||
|
attrs={'intensity': 0.3,
|
||||||
|
'height_attenuated': False,
|
||||||
|
'radius': 0.2,
|
||||||
|
'color': (0.9, 0.2, 0.9)})
|
||||||
|
self._puck.node.connectattr('position', self._puck.light, 'position')
|
||||||
|
|
@ -1,20 +1,22 @@
|
||||||
# ba_meta require api 7
|
# ba_meta require api 8
|
||||||
# (see https://ballistica.net/wiki/meta-tag-system)
|
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import ba
|
import babase
|
||||||
from bastd.actor.playerspaz import PlayerSpaz
|
import bauiv1 as bui
|
||||||
from bastd.actor.scoreboard import Scoreboard
|
import bascenev1 as bs
|
||||||
from bastd.game.deathmatch import DeathMatchGame
|
from bascenev1lib.actor.playerspaz import PlayerSpaz
|
||||||
|
from bascenev1lib.actor.scoreboard import Scoreboard
|
||||||
|
from bascenev1lib.game.deathmatch import DeathMatchGame
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any, Sequence
|
from typing import Any, Sequence
|
||||||
|
|
||||||
|
|
||||||
lang = ba.app.lang.language
|
lang = bs.app.lang.language
|
||||||
|
|
||||||
if lang == 'Spanish':
|
if lang == 'Spanish':
|
||||||
name = 'Super Boxeo'
|
name = 'Super Boxeo'
|
||||||
|
|
@ -33,7 +35,7 @@ else:
|
||||||
class NewPlayerSpaz(PlayerSpaz):
|
class NewPlayerSpaz(PlayerSpaz):
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
player: ba.Player,
|
player: bs.Player,
|
||||||
color: Sequence[float] = (1.0, 1.0, 1.0),
|
color: Sequence[float] = (1.0, 1.0, 1.0),
|
||||||
highlight: Sequence[float] = (0.5, 0.5, 0.5),
|
highlight: Sequence[float] = (0.5, 0.5, 0.5),
|
||||||
character: str = 'Spaz',
|
character: str = 'Spaz',
|
||||||
|
|
@ -44,16 +46,16 @@ class NewPlayerSpaz(PlayerSpaz):
|
||||||
highlight=highlight,
|
highlight=highlight,
|
||||||
character=character,
|
character=character,
|
||||||
powerups_expire=powerups_expire)
|
powerups_expire=powerups_expire)
|
||||||
from bastd.gameutils import SharedObjects
|
from bascenev1lib.gameutils import SharedObjects
|
||||||
shared = SharedObjects.get()
|
shared = SharedObjects.get()
|
||||||
self._super_jump = super_jump
|
self._super_jump = super_jump
|
||||||
self.jump_mode = False
|
self.jump_mode = False
|
||||||
self.super_jump_material = ba.Material()
|
self.super_jump_material = bs.Material()
|
||||||
self.super_jump_material.add_actions(
|
self.super_jump_material.add_actions(
|
||||||
conditions=('they_have_material', shared.footing_material),
|
conditions=('they_have_material', shared.footing_material),
|
||||||
actions=(
|
actions=(
|
||||||
('call', 'at_connect', ba.Call(self.jump_state, True)),
|
('call', 'at_connect', babase.Call(self.jump_state, True)),
|
||||||
('call', 'at_disconnect', ba.Call(self.jump_state, False))
|
('call', 'at_disconnect', babase.Call(self.jump_state, False))
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
self.node.roller_materials += (self.super_jump_material, )
|
self.node.roller_materials += (self.super_jump_material, )
|
||||||
|
|
@ -68,7 +70,7 @@ class NewPlayerSpaz(PlayerSpaz):
|
||||||
"""
|
"""
|
||||||
if not self.node:
|
if not self.node:
|
||||||
return
|
return
|
||||||
t_ms = ba.time(timeformat=ba.TimeFormat.MILLISECONDS)
|
t_ms = int(bs.time() * 1000.0)
|
||||||
assert isinstance(t_ms, int)
|
assert isinstance(t_ms, int)
|
||||||
if t_ms - self.last_jump_time_ms >= self._jump_cooldown:
|
if t_ms - self.last_jump_time_ms >= self._jump_cooldown:
|
||||||
self.node.jump_pressed = True
|
self.node.jump_pressed = True
|
||||||
|
|
@ -81,15 +83,15 @@ class NewPlayerSpaz(PlayerSpaz):
|
||||||
self.node.position[0],
|
self.node.position[0],
|
||||||
self.node.position[1],
|
self.node.position[1],
|
||||||
self.node.position[2],
|
self.node.position[2],
|
||||||
0, 0, 0, 150, 150, 0, 0, 0, 1, 0
|
0, 0, 0, 95, 95, 0, 0, 0, 1, 0
|
||||||
)
|
)
|
||||||
ba.timer(0.0, do_jump)
|
bs.timer(0.0, do_jump)
|
||||||
ba.timer(0.1, do_jump)
|
bs.timer(0.1, do_jump)
|
||||||
ba.timer(0.2, do_jump)
|
bs.timer(0.2, do_jump)
|
||||||
self._turbo_filter_add_press('jump')
|
self._turbo_filter_add_press('jump')
|
||||||
|
|
||||||
|
|
||||||
# ba_meta export game
|
# ba_meta export bascenev1.GameActivity
|
||||||
class BoxingGame(DeathMatchGame):
|
class BoxingGame(DeathMatchGame):
|
||||||
|
|
||||||
name = name
|
name = name
|
||||||
|
|
@ -97,16 +99,16 @@ class BoxingGame(DeathMatchGame):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_available_settings(
|
def get_available_settings(
|
||||||
cls, sessiontype: type[ba.Session]
|
cls, sessiontype: type[bs.Session]
|
||||||
) -> list[ba.Setting]:
|
) -> list[babase.Setting]:
|
||||||
settings = [
|
settings = [
|
||||||
ba.IntSetting(
|
bs.IntSetting(
|
||||||
'Kills to Win Per Player',
|
'Kills to Win Per Player',
|
||||||
min_value=1,
|
min_value=1,
|
||||||
default=5,
|
default=5,
|
||||||
increment=1,
|
increment=1,
|
||||||
),
|
),
|
||||||
ba.IntChoiceSetting(
|
bs.IntChoiceSetting(
|
||||||
'Time Limit',
|
'Time Limit',
|
||||||
choices=[
|
choices=[
|
||||||
('None', 0),
|
('None', 0),
|
||||||
|
|
@ -118,7 +120,7 @@ class BoxingGame(DeathMatchGame):
|
||||||
],
|
],
|
||||||
default=0,
|
default=0,
|
||||||
),
|
),
|
||||||
ba.FloatChoiceSetting(
|
bs.FloatChoiceSetting(
|
||||||
'Respawn Times',
|
'Respawn Times',
|
||||||
choices=[
|
choices=[
|
||||||
('Shorter', 0.25),
|
('Shorter', 0.25),
|
||||||
|
|
@ -129,9 +131,9 @@ class BoxingGame(DeathMatchGame):
|
||||||
],
|
],
|
||||||
default=1.0,
|
default=1.0,
|
||||||
),
|
),
|
||||||
ba.BoolSetting(super_jump_text, default=False),
|
bs.BoolSetting(super_jump_text, default=False),
|
||||||
ba.BoolSetting(enable_powerups, default=False),
|
bs.BoolSetting(enable_powerups, default=False),
|
||||||
ba.BoolSetting('Epic Mode', default=False),
|
bs.BoolSetting('Epic Mode', default=False),
|
||||||
]
|
]
|
||||||
|
|
||||||
# In teams mode, a suicide gives a point to the other team, but in
|
# In teams mode, a suicide gives a point to the other team, but in
|
||||||
|
|
@ -139,9 +141,9 @@ class BoxingGame(DeathMatchGame):
|
||||||
# this at zero to benefit new players, but pro players might like to
|
# this at zero to benefit new players, but pro players might like to
|
||||||
# be able to go negative. (to avoid a strategy of just
|
# be able to go negative. (to avoid a strategy of just
|
||||||
# suiciding until you get a good drop)
|
# suiciding until you get a good drop)
|
||||||
if issubclass(sessiontype, ba.FreeForAllSession):
|
if issubclass(sessiontype, bs.FreeForAllSession):
|
||||||
settings.append(
|
settings.append(
|
||||||
ba.BoolSetting('Allow Negative Scores', default=False)
|
bs.BoolSetting('Allow Negative Scores', default=False)
|
||||||
)
|
)
|
||||||
|
|
||||||
return settings
|
return settings
|
||||||
|
|
@ -150,7 +152,7 @@ class BoxingGame(DeathMatchGame):
|
||||||
super().__init__(settings)
|
super().__init__(settings)
|
||||||
self._scoreboard = Scoreboard()
|
self._scoreboard = Scoreboard()
|
||||||
self._score_to_win: int | None = None
|
self._score_to_win: int | None = None
|
||||||
self._dingsound = ba.getsound('dingSmall')
|
self._dingsound = bs.getsound('dingSmall')
|
||||||
self._epic_mode = bool(settings['Epic Mode'])
|
self._epic_mode = bool(settings['Epic Mode'])
|
||||||
self._kills_to_win_per_player = int(settings['Kills to Win Per Player'])
|
self._kills_to_win_per_player = int(settings['Kills to Win Per Player'])
|
||||||
self._time_limit = float(settings['Time Limit'])
|
self._time_limit = float(settings['Time Limit'])
|
||||||
|
|
@ -163,11 +165,11 @@ class BoxingGame(DeathMatchGame):
|
||||||
# Base class overrides.
|
# Base class overrides.
|
||||||
self.slow_motion = self._epic_mode
|
self.slow_motion = self._epic_mode
|
||||||
self.default_music = (
|
self.default_music = (
|
||||||
ba.MusicType.EPIC if self._epic_mode else ba.MusicType.TO_THE_DEATH
|
bs.MusicType.EPIC if self._epic_mode else bs.MusicType.TO_THE_DEATH
|
||||||
)
|
)
|
||||||
|
|
||||||
def on_begin(self) -> None:
|
def on_begin(self) -> None:
|
||||||
ba.TeamGameActivity.on_begin(self)
|
bs.TeamGameActivity.on_begin(self)
|
||||||
self.setup_standard_time_limit(self._time_limit)
|
self.setup_standard_time_limit(self._time_limit)
|
||||||
if self._enable_powerups:
|
if self._enable_powerups:
|
||||||
self.setup_standard_powerup_drops()
|
self.setup_standard_powerup_drops()
|
||||||
|
|
@ -180,7 +182,7 @@ class BoxingGame(DeathMatchGame):
|
||||||
|
|
||||||
def _standard_drop_powerup(self, index: int, expire: bool = True) -> None:
|
def _standard_drop_powerup(self, index: int, expire: bool = True) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bastd.actor.powerupbox import PowerupBox, PowerupBoxFactory
|
from bascenev1lib.actor.powerupbox import PowerupBox, PowerupBoxFactory
|
||||||
|
|
||||||
PowerupBox(
|
PowerupBox(
|
||||||
position=self.map.powerup_spawn_points[index],
|
position=self.map.powerup_spawn_points[index],
|
||||||
|
|
@ -191,13 +193,13 @@ class BoxingGame(DeathMatchGame):
|
||||||
expire=expire,
|
expire=expire,
|
||||||
).autoretain()
|
).autoretain()
|
||||||
|
|
||||||
def spawn_player(self, player: Player) -> ba.Actor:
|
def spawn_player(self, player: Player) -> bs.Actor:
|
||||||
import random
|
import random
|
||||||
from ba import _math
|
from babase import _math
|
||||||
from ba._gameutils import animate
|
from bascenev1._gameutils import animate
|
||||||
from ba._coopsession import CoopSession
|
from bascenev1._coopsession import CoopSession
|
||||||
|
|
||||||
if isinstance(self.session, ba.DualTeamSession):
|
if isinstance(self.session, bs.DualTeamSession):
|
||||||
position = self.map.get_start_position(player.team.id)
|
position = self.map.get_start_position(player.team.id)
|
||||||
else:
|
else:
|
||||||
# otherwise do free-for-all spawn locations
|
# otherwise do free-for-all spawn locations
|
||||||
|
|
@ -208,7 +210,7 @@ class BoxingGame(DeathMatchGame):
|
||||||
highlight = player.highlight
|
highlight = player.highlight
|
||||||
|
|
||||||
light_color = _math.normalized_color(color)
|
light_color = _math.normalized_color(color)
|
||||||
display_color = ba.safecolor(color, target_intensity=0.75)
|
display_color = babase.safecolor(color, target_intensity=0.75)
|
||||||
|
|
||||||
spaz = NewPlayerSpaz(color=color,
|
spaz = NewPlayerSpaz(color=color,
|
||||||
highlight=highlight,
|
highlight=highlight,
|
||||||
|
|
@ -224,14 +226,14 @@ class BoxingGame(DeathMatchGame):
|
||||||
|
|
||||||
# Move to the stand position and add a flash of light.
|
# Move to the stand position and add a flash of light.
|
||||||
spaz.handlemessage(
|
spaz.handlemessage(
|
||||||
ba.StandMessage(
|
bs.StandMessage(
|
||||||
position,
|
position,
|
||||||
angle if angle is not None else random.uniform(0, 360)))
|
angle if angle is not None else random.uniform(0, 360)))
|
||||||
ba.playsound(self._spawn_sound, 1, position=spaz.node.position)
|
self._spawn_sound.play(1, position=spaz.node.position)
|
||||||
light = ba.newnode('light', attrs={'color': light_color})
|
light = bs.newnode('light', attrs={'color': light_color})
|
||||||
spaz.node.connectattr('position', light, 'position')
|
spaz.node.connectattr('position', light, 'position')
|
||||||
animate(light, 'intensity', {0: 0, 0.25: 1, 0.5: 0})
|
animate(light, 'intensity', {0: 0, 0.25: 1, 0.5: 0})
|
||||||
ba.timer(0.5, light.delete)
|
bs.timer(0.5, light.delete)
|
||||||
|
|
||||||
# custom
|
# custom
|
||||||
spaz.connect_controls_to_player(enable_bomb=False)
|
spaz.connect_controls_to_player(enable_bomb=False)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# ba_meta require api 7
|
# ba_meta require api 8
|
||||||
# (see https://ballistica.net/wiki/meta-tag-system)
|
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
@ -31,19 +31,21 @@ import weakref
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import ba
|
import babase
|
||||||
|
import bauiv1 as bui
|
||||||
|
import bascenev1 as bs
|
||||||
import random
|
import random
|
||||||
from bastd.actor.flag import Flag
|
from bascenev1lib.actor.flag import Flag
|
||||||
from bastd.actor.popuptext import PopupText
|
from bascenev1lib.actor.popuptext import PopupText
|
||||||
from bastd.actor.playerspaz import PlayerSpaz
|
from bascenev1lib.actor.playerspaz import PlayerSpaz
|
||||||
from bastd.actor.scoreboard import Scoreboard
|
from bascenev1lib.actor.scoreboard import Scoreboard
|
||||||
from bastd.gameutils import SharedObjects
|
from bascenev1lib.gameutils import SharedObjects
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any, Sequence
|
from typing import Any, Sequence
|
||||||
|
|
||||||
|
|
||||||
lang = ba.app.lang.language
|
lang = bs.app.lang.language
|
||||||
if lang == 'Spanish':
|
if lang == 'Spanish':
|
||||||
name = 'Coleccionista'
|
name = 'Coleccionista'
|
||||||
description = ('Elimina a tus oponentes para robar sus cápsulas.\n'
|
description = ('Elimina a tus oponentes para robar sus cápsulas.\n'
|
||||||
|
|
@ -99,7 +101,7 @@ class FlagState(Enum):
|
||||||
HELD = 3
|
HELD = 3
|
||||||
|
|
||||||
|
|
||||||
class Player(ba.Player['Team']):
|
class Player(bs.Player['Team']):
|
||||||
"""Our player type for this game."""
|
"""Our player type for this game."""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
|
|
@ -108,15 +110,15 @@ class Player(ba.Player['Team']):
|
||||||
self.light = None
|
self.light = None
|
||||||
|
|
||||||
|
|
||||||
class Team(ba.Team[Player]):
|
class Team(bs.Team[Player]):
|
||||||
"""Our team type for this game."""
|
"""Our team type for this game."""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.score = 0
|
self.score = 0
|
||||||
|
|
||||||
|
|
||||||
# ba_meta export game
|
# ba_meta export bascenev1.GameActivity
|
||||||
class CollectorGame(ba.TeamGameActivity[Player, Team]):
|
class CollectorGame(bs.TeamGameActivity[Player, Team]):
|
||||||
|
|
||||||
name = name
|
name = name
|
||||||
description = description
|
description = description
|
||||||
|
|
@ -127,23 +129,23 @@ class CollectorGame(ba.TeamGameActivity[Player, Team]):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_available_settings(
|
def get_available_settings(
|
||||||
cls, sessiontype: type[ba.Session]
|
cls, sessiontype: type[bs.Session]
|
||||||
) -> list[ba.Setting]:
|
) -> list[babase.Setting]:
|
||||||
settings = [
|
settings = [
|
||||||
ba.IntSetting(
|
bs.IntSetting(
|
||||||
capsules_to_win,
|
capsules_to_win,
|
||||||
min_value=1,
|
min_value=1,
|
||||||
default=10,
|
default=10,
|
||||||
increment=1,
|
increment=1,
|
||||||
),
|
),
|
||||||
ba.IntSetting(
|
bs.IntSetting(
|
||||||
capsules_death,
|
capsules_death,
|
||||||
min_value=1,
|
min_value=1,
|
||||||
max_value=10,
|
max_value=10,
|
||||||
default=2,
|
default=2,
|
||||||
increment=1,
|
increment=1,
|
||||||
),
|
),
|
||||||
ba.IntChoiceSetting(
|
bs.IntChoiceSetting(
|
||||||
'Time Limit',
|
'Time Limit',
|
||||||
choices=[
|
choices=[
|
||||||
('None', 0),
|
('None', 0),
|
||||||
|
|
@ -155,7 +157,7 @@ class CollectorGame(ba.TeamGameActivity[Player, Team]):
|
||||||
],
|
],
|
||||||
default=0,
|
default=0,
|
||||||
),
|
),
|
||||||
ba.FloatChoiceSetting(
|
bs.FloatChoiceSetting(
|
||||||
'Respawn Times',
|
'Respawn Times',
|
||||||
choices=[
|
choices=[
|
||||||
('Shorter', 0.25),
|
('Shorter', 0.25),
|
||||||
|
|
@ -166,33 +168,33 @@ class CollectorGame(ba.TeamGameActivity[Player, Team]):
|
||||||
],
|
],
|
||||||
default=1.0,
|
default=1.0,
|
||||||
),
|
),
|
||||||
ba.BoolSetting(lucky_capsules, default=True),
|
bs.BoolSetting(lucky_capsules, default=True),
|
||||||
ba.BoolSetting('Epic Mode', default=False),
|
bs.BoolSetting('Epic Mode', default=False),
|
||||||
]
|
]
|
||||||
return settings
|
return settings
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def supports_session_type(cls, sessiontype: type[ba.Session]) -> bool:
|
def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool:
|
||||||
return issubclass(sessiontype, ba.DualTeamSession) or issubclass(
|
return issubclass(sessiontype, bs.DualTeamSession) or issubclass(
|
||||||
sessiontype, ba.FreeForAllSession
|
sessiontype, bs.FreeForAllSession
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_supported_maps(cls, sessiontype: type[ba.Session]) -> list[str]:
|
def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]:
|
||||||
return ba.getmaps('keep_away')
|
return bs.app.classic.getmaps('keep_away')
|
||||||
|
|
||||||
def __init__(self, settings: dict):
|
def __init__(self, settings: dict):
|
||||||
super().__init__(settings)
|
super().__init__(settings)
|
||||||
shared = SharedObjects.get()
|
shared = SharedObjects.get()
|
||||||
self._scoreboard = Scoreboard()
|
self._scoreboard = Scoreboard()
|
||||||
self._score_to_win: int | None = None
|
self._score_to_win: int | None = None
|
||||||
self._swipsound = ba.getsound('swip')
|
self._swipsound = bs.getsound('swip')
|
||||||
self._lucky_sound = ba.getsound('ding')
|
self._lucky_sound = bs.getsound('ding')
|
||||||
|
|
||||||
self._flag_pos: Sequence[float] | None = None
|
self._flag_pos: Sequence[float] | None = None
|
||||||
self._flag_state: FlagState | None = None
|
self._flag_state: FlagState | None = None
|
||||||
self._flag: Flag | None = None
|
self._flag: Flag | None = None
|
||||||
self._flag_light: ba.Node | None = None
|
self._flag_light: bs.Node | None = None
|
||||||
self._scoring_team: weakref.ref[Team] | None = None
|
self._scoring_team: weakref.ref[Team] | None = None
|
||||||
self._time_limit = float(settings['Time Limit'])
|
self._time_limit = float(settings['Time Limit'])
|
||||||
self._epic_mode = bool(settings['Epic Mode'])
|
self._epic_mode = bool(settings['Epic Mode'])
|
||||||
|
|
@ -202,19 +204,19 @@ class CollectorGame(ba.TeamGameActivity[Player, Team]):
|
||||||
self._lucky_capsules = bool(settings[lucky_capsules])
|
self._lucky_capsules = bool(settings[lucky_capsules])
|
||||||
self._capsules: list[Any] = []
|
self._capsules: list[Any] = []
|
||||||
|
|
||||||
self._capsule_model = ba.getmodel('bomb')
|
self._capsule_mesh = bs.getmesh('bomb')
|
||||||
self._capsule_tex = ba.gettexture('bombColor')
|
self._capsule_tex = bs.gettexture('bombColor')
|
||||||
self._capsule_lucky_tex = ba.gettexture('bombStickyColor')
|
self._capsule_lucky_tex = bs.gettexture('bombStickyColor')
|
||||||
self._collect_sound = ba.getsound('powerup01')
|
self._collect_sound = bs.getsound('powerup01')
|
||||||
self._lucky_collect_sound = ba.getsound('cashRegister2')
|
self._lucky_collect_sound = bs.getsound('cashRegister2')
|
||||||
|
|
||||||
self._capsule_material = ba.Material()
|
self._capsule_material = bs.Material()
|
||||||
self._capsule_material.add_actions(
|
self._capsule_material.add_actions(
|
||||||
conditions=('they_have_material', shared.player_material),
|
conditions=('they_have_material', shared.player_material),
|
||||||
actions=('call', 'at_connect', self._on_capsule_player_collide),
|
actions=('call', 'at_connect', self._on_capsule_player_collide),
|
||||||
)
|
)
|
||||||
|
|
||||||
self._flag_region_material = ba.Material()
|
self._flag_region_material = bs.Material()
|
||||||
self._flag_region_material.add_actions(
|
self._flag_region_material.add_actions(
|
||||||
conditions=('they_have_material', shared.player_material),
|
conditions=('they_have_material', shared.player_material),
|
||||||
actions=(
|
actions=(
|
||||||
|
|
@ -223,12 +225,12 @@ class CollectorGame(ba.TeamGameActivity[Player, Team]):
|
||||||
(
|
(
|
||||||
'call',
|
'call',
|
||||||
'at_connect',
|
'at_connect',
|
||||||
ba.Call(self._handle_player_flag_region_collide, True),
|
babase.Call(self._handle_player_flag_region_collide, True),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
'call',
|
'call',
|
||||||
'at_disconnect',
|
'at_disconnect',
|
||||||
ba.Call(self._handle_player_flag_region_collide, False),
|
babase.Call(self._handle_player_flag_region_collide, False),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
@ -236,7 +238,7 @@ class CollectorGame(ba.TeamGameActivity[Player, Team]):
|
||||||
# Base class overrides.
|
# Base class overrides.
|
||||||
self.slow_motion = self._epic_mode
|
self.slow_motion = self._epic_mode
|
||||||
self.default_music = (
|
self.default_music = (
|
||||||
ba.MusicType.EPIC if self._epic_mode else ba.MusicType.SCARY
|
bs.MusicType.EPIC if self._epic_mode else bs.MusicType.SCARY
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_instance_description(self) -> str | Sequence:
|
def get_instance_description(self) -> str | Sequence:
|
||||||
|
|
@ -245,7 +247,7 @@ class CollectorGame(ba.TeamGameActivity[Player, Team]):
|
||||||
def get_instance_description_short(self) -> str | Sequence:
|
def get_instance_description_short(self) -> str | Sequence:
|
||||||
return description_short, self._score_to_win
|
return description_short, self._score_to_win
|
||||||
|
|
||||||
def create_team(self, sessionteam: ba.SessionTeam) -> Team:
|
def create_team(self, sessionteam: bs.SessionTeam) -> Team:
|
||||||
return Team()
|
return Team()
|
||||||
|
|
||||||
def on_team_join(self, team: Team) -> None:
|
def on_team_join(self, team: Team) -> None:
|
||||||
|
|
@ -263,18 +265,18 @@ class CollectorGame(ba.TeamGameActivity[Player, Team]):
|
||||||
)
|
)
|
||||||
self._update_scoreboard()
|
self._update_scoreboard()
|
||||||
|
|
||||||
if isinstance(self.session, ba.FreeForAllSession):
|
if isinstance(self.session, bs.FreeForAllSession):
|
||||||
self._flag_pos = self.map.get_flag_position(random.randint(0, 1))
|
self._flag_pos = self.map.get_flag_position(random.randint(0, 1))
|
||||||
else:
|
else:
|
||||||
self._flag_pos = self.map.get_flag_position(None)
|
self._flag_pos = self.map.get_flag_position(None)
|
||||||
|
|
||||||
ba.timer(1.0, self._tick, repeat=True)
|
bs.timer(1.0, self._tick, repeat=True)
|
||||||
self._flag_state = FlagState.NEW
|
self._flag_state = FlagState.NEW
|
||||||
Flag.project_stand(self._flag_pos)
|
Flag.project_stand(self._flag_pos)
|
||||||
self._flag = Flag(
|
self._flag = Flag(
|
||||||
position=self._flag_pos, touchable=False, color=(1, 1, 1)
|
position=self._flag_pos, touchable=False, color=(1, 1, 1)
|
||||||
)
|
)
|
||||||
self._flag_light = ba.newnode(
|
self._flag_light = bs.newnode(
|
||||||
'light',
|
'light',
|
||||||
attrs={
|
attrs={
|
||||||
'position': self._flag_pos,
|
'position': self._flag_pos,
|
||||||
|
|
@ -286,7 +288,7 @@ class CollectorGame(ba.TeamGameActivity[Player, Team]):
|
||||||
)
|
)
|
||||||
# Flag region.
|
# Flag region.
|
||||||
flagmats = [self._flag_region_material, shared.region_material]
|
flagmats = [self._flag_region_material, shared.region_material]
|
||||||
ba.newnode(
|
bs.newnode(
|
||||||
'region',
|
'region',
|
||||||
attrs={
|
attrs={
|
||||||
'position': self._flag_pos,
|
'position': self._flag_pos,
|
||||||
|
|
@ -308,7 +310,7 @@ class CollectorGame(ba.TeamGameActivity[Player, Team]):
|
||||||
if not scoring_team:
|
if not scoring_team:
|
||||||
return
|
return
|
||||||
|
|
||||||
if isinstance(self.session, ba.FreeForAllSession):
|
if isinstance(self.session, bs.FreeForAllSession):
|
||||||
players = self.players
|
players = self.players
|
||||||
else:
|
else:
|
||||||
players = scoring_team.players
|
players = scoring_team.players
|
||||||
|
|
@ -331,10 +333,7 @@ class CollectorGame(ba.TeamGameActivity[Player, Team]):
|
||||||
self._flag_pos[1]+1,
|
self._flag_pos[1]+1,
|
||||||
self._flag_pos[2]
|
self._flag_pos[2]
|
||||||
), player)
|
), player)
|
||||||
ba.playsound(
|
self._collect_sound.play(0.8, position=self._flag_pos)
|
||||||
self._collect_sound,
|
|
||||||
0.8,
|
|
||||||
position=self._flag_pos)
|
|
||||||
|
|
||||||
self._update_scoreboard()
|
self._update_scoreboard()
|
||||||
if player.capsules > 0:
|
if player.capsules > 0:
|
||||||
|
|
@ -347,7 +346,7 @@ class CollectorGame(ba.TeamGameActivity[Player, Team]):
|
||||||
self.end_game()
|
self.end_game()
|
||||||
|
|
||||||
def end_game(self) -> None:
|
def end_game(self) -> None:
|
||||||
results = ba.GameResults()
|
results = bs.GameResults()
|
||||||
for team in self.teams:
|
for team in self.teams:
|
||||||
results.set_team_score(team, team.score)
|
results.set_team_score(team, team.score)
|
||||||
self.end(results=results, announce_delay=0)
|
self.end(results=results, announce_delay=0)
|
||||||
|
|
@ -369,7 +368,7 @@ class CollectorGame(ba.TeamGameActivity[Player, Team]):
|
||||||
holding_team = list(holding_teams)[0]
|
holding_team = list(holding_teams)[0]
|
||||||
self._flag_state = FlagState.HELD
|
self._flag_state = FlagState.HELD
|
||||||
self._scoring_team = weakref.ref(holding_team)
|
self._scoring_team = weakref.ref(holding_team)
|
||||||
self._flag_light.color = ba.normalized_color(holding_team.color)
|
self._flag_light.color = babase.normalized_color(holding_team.color)
|
||||||
self._flag.node.color = holding_team.color
|
self._flag.node.color = holding_team.color
|
||||||
else:
|
else:
|
||||||
self._flag_state = FlagState.UNCONTESTED
|
self._flag_state = FlagState.UNCONTESTED
|
||||||
|
|
@ -377,12 +376,12 @@ class CollectorGame(ba.TeamGameActivity[Player, Team]):
|
||||||
self._flag_light.color = (0.2, 0.2, 0.2)
|
self._flag_light.color = (0.2, 0.2, 0.2)
|
||||||
self._flag.node.color = (1, 1, 1)
|
self._flag.node.color = (1, 1, 1)
|
||||||
if self._flag_state != prev_state:
|
if self._flag_state != prev_state:
|
||||||
ba.playsound(self._swipsound)
|
self._swipsound.play()
|
||||||
|
|
||||||
def _handle_player_flag_region_collide(self, colliding: bool) -> None:
|
def _handle_player_flag_region_collide(self, colliding: bool) -> None:
|
||||||
try:
|
try:
|
||||||
spaz = ba.getcollision().opposingnode.getdelegate(PlayerSpaz, True)
|
spaz = bs.getcollision().opposingnode.getdelegate(PlayerSpaz, True)
|
||||||
except ba.NotFoundError:
|
except bs.NotFoundError:
|
||||||
return
|
return
|
||||||
|
|
||||||
if not spaz.is_alive():
|
if not spaz.is_alive():
|
||||||
|
|
@ -442,7 +441,7 @@ class CollectorGame(ba.TeamGameActivity[Player, Team]):
|
||||||
def _on_capsule_player_collide(self) -> None:
|
def _on_capsule_player_collide(self) -> None:
|
||||||
if self.has_ended():
|
if self.has_ended():
|
||||||
return
|
return
|
||||||
collision = ba.getcollision()
|
collision = bs.getcollision()
|
||||||
|
|
||||||
# Be defensive here; we could be hitting the corpse of a player
|
# Be defensive here; we could be hitting the corpse of a player
|
||||||
# who just left/etc.
|
# who just left/etc.
|
||||||
|
|
@ -451,7 +450,7 @@ class CollectorGame(ba.TeamGameActivity[Player, Team]):
|
||||||
player = collision.opposingnode.getdelegate(
|
player = collision.opposingnode.getdelegate(
|
||||||
PlayerSpaz, True
|
PlayerSpaz, True
|
||||||
).getplayer(Player, True)
|
).getplayer(Player, True)
|
||||||
except ba.NotFoundError:
|
except bs.NotFoundError:
|
||||||
return
|
return
|
||||||
|
|
||||||
if not player.is_alive():
|
if not player.is_alive():
|
||||||
|
|
@ -465,30 +464,24 @@ class CollectorGame(ba.TeamGameActivity[Player, Team]):
|
||||||
scale=1.5,
|
scale=1.5,
|
||||||
position=capsule.node.position
|
position=capsule.node.position
|
||||||
).autoretain()
|
).autoretain()
|
||||||
ba.playsound(
|
self._lucky_collect_sound.play(1.0, position=capsule.node.position)
|
||||||
self._lucky_collect_sound,
|
bs.emitfx(
|
||||||
1.0,
|
|
||||||
position=capsule.node.position)
|
|
||||||
ba.emitfx(
|
|
||||||
position=capsule.node.position,
|
position=capsule.node.position,
|
||||||
velocity=(0, 0, 0),
|
velocity=(0, 0, 0),
|
||||||
count=int(6.4+random.random()*24),
|
count=int(6.4+random.random()*24),
|
||||||
scale=1.2,
|
scale=1.2,
|
||||||
spread=2.0,
|
spread=2.0,
|
||||||
chunk_type='spark')
|
chunk_type='spark')
|
||||||
ba.emitfx(
|
bs.emitfx(
|
||||||
position=capsule.node.position,
|
position=capsule.node.position,
|
||||||
velocity=(0, 0, 0),
|
velocity=(0, 0, 0),
|
||||||
count=int(4.0+random.random()*6),
|
count=int(4.0+random.random()*6),
|
||||||
emit_type='tendrils')
|
emit_type='tendrils')
|
||||||
else:
|
else:
|
||||||
player.capsules += 1
|
player.capsules += 1
|
||||||
ba.playsound(
|
self._collect_sound.play(0.6, position=capsule.node.position)
|
||||||
self._collect_sound,
|
|
||||||
0.6,
|
|
||||||
position=capsule.node.position)
|
|
||||||
# create a flash
|
# create a flash
|
||||||
light = ba.newnode(
|
light = bs.newnode(
|
||||||
'light',
|
'light',
|
||||||
attrs={
|
attrs={
|
||||||
'position': capsule.node.position,
|
'position': capsule.node.position,
|
||||||
|
|
@ -499,27 +492,27 @@ class CollectorGame(ba.TeamGameActivity[Player, Team]):
|
||||||
# Create a short text informing about your inventory
|
# Create a short text informing about your inventory
|
||||||
self._handle_capsule_storage(player.position, player)
|
self._handle_capsule_storage(player.position, player)
|
||||||
|
|
||||||
ba.animate(light, 'intensity', {
|
bs.animate(light, 'intensity', {
|
||||||
0: 0,
|
0: 0,
|
||||||
0.1: 0.5,
|
0.1: 0.5,
|
||||||
0.2: 0
|
0.2: 0
|
||||||
}, loop=False)
|
}, loop=False)
|
||||||
ba.timer(0.2, light.delete)
|
bs.timer(0.2, light.delete)
|
||||||
capsule.handlemessage(ba.DieMessage())
|
capsule.handlemessage(bs.DieMessage())
|
||||||
|
|
||||||
def _update_player_light(self, player: Player, capsules: int) -> None:
|
def _update_player_light(self, player: Player, capsules: int) -> None:
|
||||||
if player.light:
|
if player.light:
|
||||||
intensity = 0.04 * capsules
|
intensity = 0.04 * capsules
|
||||||
ba.animate(player.light, 'intensity', {
|
bs.animate(player.light, 'intensity', {
|
||||||
0.0: player.light.intensity,
|
0.0: player.light.intensity,
|
||||||
0.1: intensity
|
0.1: intensity
|
||||||
})
|
})
|
||||||
|
|
||||||
def newintensity():
|
def newintensity():
|
||||||
player.light.intensity = intensity
|
player.light.intensity = intensity
|
||||||
ba.timer(0.1, newintensity)
|
bs.timer(0.1, newintensity)
|
||||||
else:
|
else:
|
||||||
player.light = ba.newnode(
|
player.light = bs.newnode(
|
||||||
'light',
|
'light',
|
||||||
attrs={
|
attrs={
|
||||||
'height_attenuated': False,
|
'height_attenuated': False,
|
||||||
|
|
@ -558,7 +551,7 @@ class CollectorGame(ba.TeamGameActivity[Player, Team]):
|
||||||
self._update_player_light(player, capsules)
|
self._update_player_light(player, capsules)
|
||||||
|
|
||||||
def handlemessage(self, msg: Any) -> Any:
|
def handlemessage(self, msg: Any) -> Any:
|
||||||
if isinstance(msg, ba.PlayerDiedMessage):
|
if isinstance(msg, bs.PlayerDiedMessage):
|
||||||
super().handlemessage(msg) # Augment default.
|
super().handlemessage(msg) # Augment default.
|
||||||
# No longer can count as time_at_flag once dead.
|
# No longer can count as time_at_flag once dead.
|
||||||
player = msg.getplayer(Player)
|
player = msg.getplayer(Player)
|
||||||
|
|
@ -572,7 +565,7 @@ class CollectorGame(ba.TeamGameActivity[Player, Team]):
|
||||||
return super().handlemessage(msg)
|
return super().handlemessage(msg)
|
||||||
|
|
||||||
|
|
||||||
class Capsule(ba.Actor):
|
class Capsule(bs.Actor):
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
position: Sequence[float] = (0.0, 1.0, 0.0),
|
position: Sequence[float] = (0.0, 1.0, 0.0),
|
||||||
|
|
@ -586,12 +579,12 @@ class Capsule(ba.Actor):
|
||||||
self._spawn_pos = (position[0], position[1], position[2])
|
self._spawn_pos = (position[0], position[1], position[2])
|
||||||
|
|
||||||
if lucky:
|
if lucky:
|
||||||
ba.playsound(activity._lucky_sound, 1.0, self._spawn_pos)
|
activity._lucky_sound.play(1.0, self._spawn_pos)
|
||||||
|
|
||||||
self.node = ba.newnode(
|
self.node = bs.newnode(
|
||||||
'prop',
|
'prop',
|
||||||
attrs={
|
attrs={
|
||||||
'model': activity._capsule_model,
|
'mesh': activity._capsule_mesh,
|
||||||
'color_texture': activity._capsule_lucky_tex if lucky else (
|
'color_texture': activity._capsule_lucky_tex if lucky else (
|
||||||
activity._capsule_tex),
|
activity._capsule_tex),
|
||||||
'body': 'crate' if lucky else 'capsule',
|
'body': 'crate' if lucky else 'capsule',
|
||||||
|
|
@ -606,12 +599,12 @@ class Capsule(ba.Actor):
|
||||||
shared.object_material, activity._capsule_material]
|
shared.object_material, activity._capsule_material]
|
||||||
},
|
},
|
||||||
delegate=self)
|
delegate=self)
|
||||||
ba.animate(self.node, 'model_scale', {
|
bs.animate(self.node, 'mesh_scale', {
|
||||||
0.0: 0.0,
|
0.0: 0.0,
|
||||||
0.1: 0.9 if lucky else 0.6,
|
0.1: 0.9 if lucky else 0.6,
|
||||||
0.16: 0.8 if lucky else 0.5
|
0.16: 0.8 if lucky else 0.5
|
||||||
})
|
})
|
||||||
self._light_capsule = ba.newnode(
|
self._light_capsule = bs.newnode(
|
||||||
'light',
|
'light',
|
||||||
attrs={
|
attrs={
|
||||||
'position': self._spawn_pos,
|
'position': self._spawn_pos,
|
||||||
|
|
@ -622,16 +615,16 @@ class Capsule(ba.Actor):
|
||||||
self.node.connectattr('position', self._light_capsule, 'position')
|
self.node.connectattr('position', self._light_capsule, 'position')
|
||||||
|
|
||||||
def handlemessage(self, msg: Any):
|
def handlemessage(self, msg: Any):
|
||||||
if isinstance(msg, ba.DieMessage):
|
if isinstance(msg, bs.DieMessage):
|
||||||
self.node.delete()
|
self.node.delete()
|
||||||
ba.animate(self._light_capsule, 'intensity', {
|
bs.animate(self._light_capsule, 'intensity', {
|
||||||
0: 1.0,
|
0: 1.0,
|
||||||
0.05: 0.0
|
0.05: 0.0
|
||||||
}, loop=False)
|
}, loop=False)
|
||||||
ba.timer(0.05, self._light_capsule.delete)
|
bs.timer(0.05, self._light_capsule.delete)
|
||||||
elif isinstance(msg, ba.OutOfBoundsMessage):
|
elif isinstance(msg, bs.OutOfBoundsMessage):
|
||||||
self.handlemessage(ba.DieMessage())
|
self.handlemessage(bs.DieMessage())
|
||||||
elif isinstance(msg, ba.HitMessage):
|
elif isinstance(msg, bs.HitMessage):
|
||||||
self.node.handlemessage(
|
self.node.handlemessage(
|
||||||
'impulse',
|
'impulse',
|
||||||
msg.pos[0], msg.pos[1], msg.pos[2],
|
msg.pos[0], msg.pos[1], msg.pos[2],
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
# ba_meta require api 7
|
# ba_meta require api 8
|
||||||
"""
|
"""
|
||||||
DemolitionWar - BombFight on wooden floor flying in air.
|
DemolitionWar - BombFight on wooden floor flying in air.
|
||||||
Author: Mr.Smoothy
|
Author: Mr.Smoothy
|
||||||
|
|
@ -12,23 +12,26 @@ from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import ba
|
import babase
|
||||||
from bastd.game.elimination import EliminationGame, Player
|
import bauiv1 as bui
|
||||||
from bastd.gameutils import SharedObjects
|
import bascenev1 as bs
|
||||||
from bastd.actor.bomb import BombFactory
|
from bascenev1 import _map
|
||||||
|
from bascenev1lib.game.elimination import EliminationGame, Player
|
||||||
|
from bascenev1lib.gameutils import SharedObjects
|
||||||
|
from bascenev1lib.actor.bomb import BombFactory
|
||||||
import random
|
import random
|
||||||
from bastd.actor.playerspaz import PlayerSpaz
|
from bascenev1lib.actor.playerspaz import PlayerSpaz
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any, Sequence
|
from typing import Any, Sequence
|
||||||
|
|
||||||
# ba_meta export game
|
# ba_meta export bascenev1.GameActivity
|
||||||
|
|
||||||
|
|
||||||
class DemolitionWar(EliminationGame):
|
class DemolitionWar(EliminationGame):
|
||||||
name = 'DemolitionWar'
|
name = 'DemolitionWar'
|
||||||
description = 'Last remaining alive wins.'
|
description = 'Last remaining alive wins.'
|
||||||
scoreconfig = ba.ScoreConfig(
|
scoreconfig = bs.ScoreConfig(
|
||||||
label='Survived', scoretype=ba.ScoreType.SECONDS, none_is_winner=True
|
label='Survived', scoretype=bs.ScoreType.SECONDS, none_is_winner=True
|
||||||
)
|
)
|
||||||
# Show messages when players die since it's meaningful here.
|
# Show messages when players die since it's meaningful here.
|
||||||
announce_player_deaths = True
|
announce_player_deaths = True
|
||||||
|
|
@ -37,17 +40,17 @@ class DemolitionWar(EliminationGame):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_available_settings(
|
def get_available_settings(
|
||||||
cls, sessiontype: type[ba.Session]
|
cls, sessiontype: type[bs.Session]
|
||||||
) -> list[ba.Setting]:
|
) -> list[babase.Setting]:
|
||||||
settings = [
|
settings = [
|
||||||
ba.IntSetting(
|
bs.IntSetting(
|
||||||
'Lives Per Player',
|
'Lives Per Player',
|
||||||
default=1,
|
default=1,
|
||||||
min_value=1,
|
min_value=1,
|
||||||
max_value=10,
|
max_value=10,
|
||||||
increment=1,
|
increment=1,
|
||||||
),
|
),
|
||||||
ba.IntChoiceSetting(
|
bs.IntChoiceSetting(
|
||||||
'Time Limit',
|
'Time Limit',
|
||||||
choices=[
|
choices=[
|
||||||
('None', 0),
|
('None', 0),
|
||||||
|
|
@ -59,7 +62,7 @@ class DemolitionWar(EliminationGame):
|
||||||
],
|
],
|
||||||
default=0,
|
default=0,
|
||||||
),
|
),
|
||||||
ba.FloatChoiceSetting(
|
bs.FloatChoiceSetting(
|
||||||
'Respawn Times',
|
'Respawn Times',
|
||||||
choices=[
|
choices=[
|
||||||
('Shorter', 0.25),
|
('Shorter', 0.25),
|
||||||
|
|
@ -70,23 +73,23 @@ class DemolitionWar(EliminationGame):
|
||||||
],
|
],
|
||||||
default=1.0,
|
default=1.0,
|
||||||
),
|
),
|
||||||
ba.BoolSetting('Epic Mode', default=False),
|
bs.BoolSetting('Epic Mode', default=False),
|
||||||
]
|
]
|
||||||
if issubclass(sessiontype, ba.DualTeamSession):
|
if issubclass(sessiontype, bs.DualTeamSession):
|
||||||
settings.append(ba.BoolSetting('Solo Mode', default=False))
|
settings.append(bs.BoolSetting('Solo Mode', default=False))
|
||||||
settings.append(
|
settings.append(
|
||||||
ba.BoolSetting('Balance Total Lives', default=False)
|
bs.BoolSetting('Balance Total Lives', default=False)
|
||||||
)
|
)
|
||||||
return settings
|
return settings
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def supports_session_type(cls, sessiontype: type[ba.Session]) -> bool:
|
def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool:
|
||||||
return issubclass(sessiontype, ba.DualTeamSession) or issubclass(
|
return issubclass(sessiontype, bs.DualTeamSession) or issubclass(
|
||||||
sessiontype, ba.FreeForAllSession
|
sessiontype, bs.FreeForAllSession
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_supported_maps(cls, sessiontype: type[ba.Session]) -> list[str]:
|
def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]:
|
||||||
return ['Wooden Floor']
|
return ['Wooden Floor']
|
||||||
|
|
||||||
def __init__(self, settings: dict):
|
def __init__(self, settings: dict):
|
||||||
|
|
@ -95,7 +98,7 @@ class DemolitionWar(EliminationGame):
|
||||||
self._solo_mode = False
|
self._solo_mode = False
|
||||||
self._balance_total_lives = False
|
self._balance_total_lives = False
|
||||||
|
|
||||||
def spawn_player(self, player: Player) -> ba.Actor:
|
def spawn_player(self, player: Player) -> bs.Actor:
|
||||||
p = [-6, -4.3, -2.6, -0.9, 0.8, 2.5, 4.2, 5.9]
|
p = [-6, -4.3, -2.6, -0.9, 0.8, 2.5, 4.2, 5.9]
|
||||||
q = [-4, -2.3, -0.6, 1.1, 2.8, 4.5]
|
q = [-4, -2.3, -0.6, 1.1, 2.8, 4.5]
|
||||||
|
|
||||||
|
|
@ -118,23 +121,23 @@ class DemolitionWar(EliminationGame):
|
||||||
self.map_extend()
|
self.map_extend()
|
||||||
|
|
||||||
def on_blast(self):
|
def on_blast(self):
|
||||||
node = ba.getcollision().sourcenode
|
node = bs.getcollision().sourcenode
|
||||||
ba.emitfx((node.position[0], 0.9, node.position[2]),
|
bs.emitfx((node.position[0], 0.9, node.position[2]),
|
||||||
(0, 2, 0), 30, 1, spread=1, chunk_type='splinter')
|
(0, 2, 0), 30, 1, spread=1, chunk_type='splinter')
|
||||||
ba.timer(0.1, ba.Call(node.delete))
|
bs.timer(0.1, babase.Call(node.delete))
|
||||||
|
|
||||||
def map_extend(self):
|
def map_extend(self):
|
||||||
# TODO need to improve here , so we can increase size of map easily with settings
|
# TODO need to improve here , so we can increase size of map easily with settings
|
||||||
p = [-6, -4.3, -2.6, -0.9, 0.8, 2.5, 4.2, 5.9]
|
p = [-6, -4.3, -2.6, -0.9, 0.8, 2.5, 4.2, 5.9]
|
||||||
q = [-4, -2.3, -0.6, 1.1, 2.8, 4.5]
|
q = [-4, -2.3, -0.6, 1.1, 2.8, 4.5]
|
||||||
factory = BombFactory.get()
|
factory = BombFactory.get()
|
||||||
self.ramp_bomb = ba.Material()
|
self.ramp_bomb = bs.Material()
|
||||||
self.ramp_bomb.add_actions(
|
self.ramp_bomb.add_actions(
|
||||||
conditions=('they_have_material', factory.bomb_material),
|
conditions=('they_have_material', factory.bomb_material),
|
||||||
actions=(
|
actions=(
|
||||||
('modify_part_collision', 'collide', True),
|
('modify_part_collision', 'collide', True),
|
||||||
('modify_part_collision', 'physical', True),
|
('modify_part_collision', 'physical', True),
|
||||||
('call', 'at_connect', ba.Call(self.on_blast))
|
('call', 'at_connect', babase.Call(self.on_blast))
|
||||||
))
|
))
|
||||||
self.ramps = []
|
self.ramps = []
|
||||||
for i in p:
|
for i in p:
|
||||||
|
|
@ -144,7 +147,7 @@ class DemolitionWar(EliminationGame):
|
||||||
def create_ramp(self, x, z):
|
def create_ramp(self, x, z):
|
||||||
|
|
||||||
shared = SharedObjects.get()
|
shared = SharedObjects.get()
|
||||||
self._real_collied_material = ba.Material()
|
self._real_collied_material = bs.Material()
|
||||||
|
|
||||||
self._real_collied_material.add_actions(
|
self._real_collied_material.add_actions(
|
||||||
actions=(
|
actions=(
|
||||||
|
|
@ -152,32 +155,32 @@ class DemolitionWar(EliminationGame):
|
||||||
('modify_part_collision', 'physical', True)
|
('modify_part_collision', 'physical', True)
|
||||||
|
|
||||||
))
|
))
|
||||||
self.mat = ba.Material()
|
self.mat = bs.Material()
|
||||||
self.mat.add_actions(
|
self.mat.add_actions(
|
||||||
actions=(('modify_part_collision', 'physical', False),
|
actions=(('modify_part_collision', 'physical', False),
|
||||||
('modify_part_collision', 'collide', False))
|
('modify_part_collision', 'collide', False))
|
||||||
)
|
)
|
||||||
pos = (x, 0, z)
|
pos = (x, 0, z)
|
||||||
ud_1_r = ba.newnode('region', attrs={'position': pos, 'scale': (1.5, 1, 1.5), 'type': 'box', 'materials': [
|
ud_1_r = bs.newnode('region', attrs={'position': pos, 'scale': (1.5, 1, 1.5), 'type': 'box', 'materials': [
|
||||||
shared.footing_material, self._real_collied_material, self.ramp_bomb]})
|
shared.footing_material, self._real_collied_material, self.ramp_bomb]})
|
||||||
|
|
||||||
node = ba.newnode('prop',
|
node = bs.newnode('prop',
|
||||||
owner=ud_1_r,
|
owner=ud_1_r,
|
||||||
attrs={
|
attrs={
|
||||||
'model': ba.getmodel('image1x1'),
|
'mesh': bs.getmesh('image1x1'),
|
||||||
'light_model': ba.getmodel('powerupSimple'),
|
'light_mesh': bs.getmesh('powerupSimple'),
|
||||||
'position': (2, 7, 2),
|
'position': (2, 7, 2),
|
||||||
'body': 'puck',
|
'body': 'puck',
|
||||||
'shadow_size': 0.0,
|
'shadow_size': 0.0,
|
||||||
'velocity': (0, 0, 0),
|
'velocity': (0, 0, 0),
|
||||||
'color_texture': ba.gettexture('tnt'),
|
'color_texture': bs.gettexture('tnt'),
|
||||||
'model_scale': 1.5,
|
'mesh_scale': 1.5,
|
||||||
'reflection_scale': [1.5],
|
'reflection_scale': [1.5],
|
||||||
'materials': [self.mat, shared.object_material, shared.footing_material],
|
'materials': [self.mat, shared.object_material, shared.footing_material],
|
||||||
'density': 9000000000
|
'density': 9000000000
|
||||||
})
|
})
|
||||||
node.changerotation(1, 0, 0)
|
# node.changerotation(1, 0, 0)
|
||||||
mnode = ba.newnode('math',
|
mnode = bs.newnode('math',
|
||||||
owner=ud_1_r,
|
owner=ud_1_r,
|
||||||
attrs={
|
attrs={
|
||||||
'input1': (0, 0.6, 0),
|
'input1': (0, 0.6, 0),
|
||||||
|
|
@ -218,7 +221,7 @@ class mapdefs:
|
||||||
points['tnt1'] = (-0.08421587483, 0.9515026107, -0.7762602271)
|
points['tnt1'] = (-0.08421587483, 0.9515026107, -0.7762602271)
|
||||||
|
|
||||||
|
|
||||||
class WoodenFloor(ba.Map):
|
class WoodenFloor(bs._map.Map): # ahdunno if this is correct way, change if u find better way
|
||||||
"""Stadium map for football games."""
|
"""Stadium map for football games."""
|
||||||
defs = mapdefs
|
defs = mapdefs
|
||||||
defs.points['spawn1'] = (-12.03866341, 0.02275111462, 0.0) + (0.5, 1.0, 4.0)
|
defs.points['spawn1'] = (-12.03866341, 0.02275111462, 0.0) + (0.5, 1.0, 4.0)
|
||||||
|
|
@ -238,15 +241,15 @@ class WoodenFloor(ba.Map):
|
||||||
def on_preload(cls) -> Any:
|
def on_preload(cls) -> Any:
|
||||||
data: dict[str, Any] = {
|
data: dict[str, Any] = {
|
||||||
|
|
||||||
'model_bg': ba.getmodel('doomShroomBG'),
|
'mesh_bg': bs.getmesh('doomShroomBG'),
|
||||||
'bg_vr_fill_model': ba.getmodel('natureBackgroundVRFill'),
|
'bg_vr_fill_mesh': bs.getmesh('natureBackgroundVRFill'),
|
||||||
'collide_model': ba.getcollidemodel('bridgitLevelCollide'),
|
'collide_mesh': bs.getcollisionmesh('bridgitLevelCollide'),
|
||||||
'tex': ba.gettexture('bridgitLevelColor'),
|
'tex': bs.gettexture('bridgitLevelColor'),
|
||||||
'model_bg_tex': ba.gettexture('doomShroomBGColor'),
|
'mesh_bg_tex': bs.gettexture('doomShroomBGColor'),
|
||||||
'collide_bg': ba.getcollidemodel('natureBackgroundCollide'),
|
'collide_bg': bs.getcollisionmesh('natureBackgroundCollide'),
|
||||||
'railing_collide_model':
|
'railing_collide_mesh':
|
||||||
(ba.getcollidemodel('bridgitLevelRailingCollide')),
|
(bs.getcollisionmesh('bridgitLevelRailingCollide')),
|
||||||
'bg_material': ba.Material()
|
'bg_material': bs.Material()
|
||||||
}
|
}
|
||||||
data['bg_material'].add_actions(actions=('modify_part_collision',
|
data['bg_material'].add_actions(actions=('modify_part_collision',
|
||||||
'friction', 10.0))
|
'friction', 10.0))
|
||||||
|
|
@ -255,23 +258,23 @@ class WoodenFloor(ba.Map):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
shared = SharedObjects.get()
|
shared = SharedObjects.get()
|
||||||
self.background = ba.newnode(
|
self.background = bs.newnode(
|
||||||
'terrain',
|
'terrain',
|
||||||
attrs={
|
attrs={
|
||||||
'model': self.preloaddata['model_bg'],
|
'mesh': self.preloaddata['mesh_bg'],
|
||||||
'lighting': False,
|
'lighting': False,
|
||||||
'background': True,
|
'background': True,
|
||||||
'color_texture': self.preloaddata['model_bg_tex']
|
'color_texture': self.preloaddata['mesh_bg_tex']
|
||||||
})
|
})
|
||||||
self.vr = ba.newnode('terrain',
|
self.vr = bs.newnode('terrain',
|
||||||
attrs={
|
attrs={
|
||||||
'model': self.preloaddata['bg_vr_fill_model'],
|
'mesh': self.preloaddata['bg_vr_fill_mesh'],
|
||||||
'lighting': False,
|
'lighting': False,
|
||||||
'vr_only': True,
|
'vr_only': True,
|
||||||
'background': True,
|
'background': True,
|
||||||
'color_texture': self.preloaddata['model_bg_tex']
|
'color_texture': self.preloaddata['mesh_bg_tex']
|
||||||
})
|
})
|
||||||
gnode = ba.getactivity().globalsnode
|
gnode = bs.getactivity().globalsnode
|
||||||
gnode.tint = (1.3, 1.2, 1.0)
|
gnode.tint = (1.3, 1.2, 1.0)
|
||||||
gnode.ambient_color = (1.3, 1.2, 1.0)
|
gnode.ambient_color = (1.3, 1.2, 1.0)
|
||||||
gnode.vignette_outer = (0.57, 0.57, 0.57)
|
gnode.vignette_outer = (0.57, 0.57, 0.57)
|
||||||
|
|
@ -280,7 +283,7 @@ class WoodenFloor(ba.Map):
|
||||||
gnode.vr_near_clip = 0.5
|
gnode.vr_near_clip = 0.5
|
||||||
|
|
||||||
def is_point_near_edge(self,
|
def is_point_near_edge(self,
|
||||||
point: ba.Vec3,
|
point: babase.Vec3,
|
||||||
running: bool = False) -> bool:
|
running: bool = False) -> bool:
|
||||||
box_position = self.defs.boxes['edge_box'][0:3]
|
box_position = self.defs.boxes['edge_box'][0:3]
|
||||||
box_scale = self.defs.boxes['edge_box'][6:9]
|
box_scale = self.defs.boxes['edge_box'][6:9]
|
||||||
|
|
@ -290,15 +293,15 @@ class WoodenFloor(ba.Map):
|
||||||
|
|
||||||
def _handle_player_collide(self):
|
def _handle_player_collide(self):
|
||||||
try:
|
try:
|
||||||
player = ba.getcollision().opposingnode.getdelegate(
|
player = bs.getcollision().opposingnode.getdelegate(
|
||||||
PlayerSpaz, True)
|
PlayerSpaz, True)
|
||||||
except ba.NotFoundError:
|
except bs.NotFoundError:
|
||||||
return
|
return
|
||||||
if player.is_alive():
|
if player.is_alive():
|
||||||
player.shatter(True)
|
player.shatter(True)
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
ba._map.register_map(WoodenFloor)
|
bs._map.register_map(WoodenFloor)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
|
||||||
|
|
@ -6,18 +6,20 @@
|
||||||
|
|
||||||
# Feel free to edit.
|
# Feel free to edit.
|
||||||
|
|
||||||
# ba_meta require api 7
|
# ba_meta require api 8
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import ba
|
import babase
|
||||||
|
import bauiv1 as bui
|
||||||
|
import bascenev1 as bs
|
||||||
from random import choice
|
from random import choice
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from bastd.actor.bomb import Blast
|
from bascenev1lib.actor.bomb import Blast
|
||||||
from bastd.actor.popuptext import PopupText
|
from bascenev1lib.actor.popuptext import PopupText
|
||||||
from bastd.actor.powerupbox import PowerupBox
|
from bascenev1lib.actor.powerupbox import PowerupBox
|
||||||
from bastd.actor.onscreencountdown import OnScreenCountdown
|
from bascenev1lib.actor.onscreencountdown import OnScreenCountdown
|
||||||
from bastd.gameutils import SharedObjects
|
from bascenev1lib.gameutils import SharedObjects
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import NoReturn, Sequence, Any
|
from typing import NoReturn, Sequence, Any
|
||||||
|
|
@ -48,13 +50,13 @@ ball_type_dict: dict[BallType, int] = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Ball(ba.Actor):
|
class Ball(bs.Actor):
|
||||||
""" Shooting Ball """
|
""" Shooting Ball """
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
position: Sequence[float],
|
position: Sequence[float],
|
||||||
velocity: Sequence[float],
|
velocity: Sequence[float],
|
||||||
texture: ba.Texture,
|
texture: babase.Texture,
|
||||||
body_scale: float = 1.0,
|
body_scale: float = 1.0,
|
||||||
gravity_scale: float = 1.0,
|
gravity_scale: float = 1.0,
|
||||||
) -> NoReturn:
|
) -> NoReturn:
|
||||||
|
|
@ -63,7 +65,7 @@ class Ball(ba.Actor):
|
||||||
|
|
||||||
shared = SharedObjects.get()
|
shared = SharedObjects.get()
|
||||||
|
|
||||||
ball_material = ba.Material()
|
ball_material = bs.Material()
|
||||||
ball_material.add_actions(
|
ball_material.add_actions(
|
||||||
conditions=(
|
conditions=(
|
||||||
(
|
(
|
||||||
|
|
@ -77,7 +79,7 @@ class Ball(ba.Actor):
|
||||||
actions=('modify_node_collision', 'collide', False),
|
actions=('modify_node_collision', 'collide', False),
|
||||||
)
|
)
|
||||||
|
|
||||||
self.node = ba.newnode(
|
self.node = bs.newnode(
|
||||||
'prop',
|
'prop',
|
||||||
delegate=self,
|
delegate=self,
|
||||||
attrs={
|
attrs={
|
||||||
|
|
@ -85,8 +87,8 @@ class Ball(ba.Actor):
|
||||||
'position': position,
|
'position': position,
|
||||||
'velocity': velocity,
|
'velocity': velocity,
|
||||||
'body_scale': body_scale,
|
'body_scale': body_scale,
|
||||||
'model': ba.getmodel('frostyPelvis'),
|
'mesh': bs.getmesh('frostyPelvis'),
|
||||||
'model_scale': body_scale,
|
'mesh_scale': body_scale,
|
||||||
'color_texture': texture,
|
'color_texture': texture,
|
||||||
'gravity_scale': gravity_scale,
|
'gravity_scale': gravity_scale,
|
||||||
'density': 4.0, # increase density of ball so ball collide with player with heavy force. # ammm very bad grammer
|
'density': 4.0, # increase density of ball so ball collide with player with heavy force. # ammm very bad grammer
|
||||||
|
|
@ -95,19 +97,19 @@ class Ball(ba.Actor):
|
||||||
)
|
)
|
||||||
|
|
||||||
# die the ball manually incase the ball doesn't fall the outside of the map
|
# die the ball manually incase the ball doesn't fall the outside of the map
|
||||||
ba.timer(2.5, ba.WeakCall(self.handlemessage, ba.DieMessage()))
|
bs.timer(2.5, bs.WeakCall(self.handlemessage, bs.DieMessage()))
|
||||||
|
|
||||||
# i am not handling anything in this ball Class(except for diemessage).
|
# i am not handling anything in this ball Class(except for diemessage).
|
||||||
# all game things and logics going to be in the box class
|
# all game things and logics going to be in the box class
|
||||||
def handlemessage(self, msg: Any) -> Any:
|
def handlemessage(self, msg: Any) -> Any:
|
||||||
|
|
||||||
if isinstance(msg, ba.DieMessage):
|
if isinstance(msg, bs.DieMessage):
|
||||||
self.node.delete()
|
self.node.delete()
|
||||||
else:
|
else:
|
||||||
super().handlemessage(msg)
|
super().handlemessage(msg)
|
||||||
|
|
||||||
|
|
||||||
class Box(ba.Actor):
|
class Box(bs.Actor):
|
||||||
""" A box that spawn midle of map as a decoration perpose """
|
""" A box that spawn midle of map as a decoration perpose """
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
|
|
@ -119,7 +121,7 @@ class Box(ba.Actor):
|
||||||
|
|
||||||
shared = SharedObjects.get()
|
shared = SharedObjects.get()
|
||||||
# self.ball_jump = 0.0;
|
# self.ball_jump = 0.0;
|
||||||
no_hit_material = ba.Material()
|
no_hit_material = bs.Material()
|
||||||
# we don't need that the box was move and collide with objects.
|
# we don't need that the box was move and collide with objects.
|
||||||
no_hit_material.add_actions(
|
no_hit_material.add_actions(
|
||||||
conditions=(
|
conditions=(
|
||||||
|
|
@ -142,25 +144,25 @@ class Box(ba.Actor):
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
self.node = ba.newnode(
|
self.node = bs.newnode(
|
||||||
'prop',
|
'prop',
|
||||||
delegate=self,
|
delegate=self,
|
||||||
attrs={
|
attrs={
|
||||||
'body': 'box',
|
'body': 'box',
|
||||||
'position': position,
|
'position': position,
|
||||||
'model': ba.getmodel('powerup'),
|
'mesh': bs.getmesh('powerup'),
|
||||||
'light_model': ba.getmodel('powerupSimple'),
|
'light_mesh': bs.getmesh('powerupSimple'),
|
||||||
'shadow_size': 0.5,
|
'shadow_size': 0.5,
|
||||||
'body_scale': 1.4,
|
'body_scale': 1.4,
|
||||||
'model_scale': 1.4,
|
'mesh_scale': 1.4,
|
||||||
'color_texture': ba.gettexture('landMineLit'),
|
'color_texture': bs.gettexture('landMineLit'),
|
||||||
'reflection': 'powerup',
|
'reflection': 'powerup',
|
||||||
'reflection_scale': [1.0],
|
'reflection_scale': [1.0],
|
||||||
'materials': (no_hit_material,),
|
'materials': (no_hit_material,),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
# light
|
# light
|
||||||
self.light = ba.newnode(
|
self.light = bs.newnode(
|
||||||
"light",
|
"light",
|
||||||
owner=self.node,
|
owner=self.node,
|
||||||
attrs={
|
attrs={
|
||||||
|
|
@ -173,7 +175,7 @@ class Box(ba.Actor):
|
||||||
# Drawing circle and circleOutline in radius of 3,
|
# Drawing circle and circleOutline in radius of 3,
|
||||||
# so player can see that how close he is to the box.
|
# so player can see that how close he is to the box.
|
||||||
# If player is inside this circle the ball speed will increase.
|
# If player is inside this circle the ball speed will increase.
|
||||||
circle = ba.newnode(
|
circle = bs.newnode(
|
||||||
"locator",
|
"locator",
|
||||||
owner=self.node,
|
owner=self.node,
|
||||||
attrs={
|
attrs={
|
||||||
|
|
@ -187,7 +189,7 @@ class Box(ba.Actor):
|
||||||
)
|
)
|
||||||
self.node.connectattr("position", circle, "position")
|
self.node.connectattr("position", circle, "position")
|
||||||
# also adding a outline cause its look nice.
|
# also adding a outline cause its look nice.
|
||||||
circle_outline = ba.newnode(
|
circle_outline = bs.newnode(
|
||||||
"locator",
|
"locator",
|
||||||
owner=self.node,
|
owner=self.node,
|
||||||
attrs={
|
attrs={
|
||||||
|
|
@ -203,17 +205,17 @@ class Box(ba.Actor):
|
||||||
|
|
||||||
# all ball attribute that we need.
|
# all ball attribute that we need.
|
||||||
self.ball_type: BallType = BallType.EASY
|
self.ball_type: BallType = BallType.EASY
|
||||||
self.shoot_timer: ba.Timer | None = None
|
self.shoot_timer: bs.Timer | None = None
|
||||||
self.shoot_speed: float = 0.0
|
self.shoot_speed: float = 0.0
|
||||||
# this force the shoot if player is inside the red circle.
|
# this force the shoot if player is inside the red circle.
|
||||||
self.force_shoot_speed: float = 0.0
|
self.force_shoot_speed: float = 0.0
|
||||||
self.ball_mag = 3000
|
self.ball_mag = 3000
|
||||||
self.ball_gravity: float = 1.0
|
self.ball_gravity: float = 1.0
|
||||||
self.ball_tex: ba.Texture | None = None
|
self.ball_tex: babase.Texture | None = None
|
||||||
# only for Hard ball_type
|
# only for Hard ball_type
|
||||||
self.player_facing_direction: list[float, float] = [0.0, 0.0]
|
self.player_facing_direction: list[float, float] = [0.0, 0.0]
|
||||||
# ball shoot soound.
|
# ball shoot soound.
|
||||||
self.shoot_sound = ba.getsound('laserReverse')
|
self.shoot_sound = bs.getsound('laserReverse')
|
||||||
|
|
||||||
# same as "powerupdist"
|
# same as "powerupdist"
|
||||||
self.ball_type_dist: list[BallType] = []
|
self.ball_type_dist: list[BallType] = []
|
||||||
|
|
@ -240,7 +242,7 @@ class Box(ba.Actor):
|
||||||
# to finding difference between player and box.
|
# to finding difference between player and box.
|
||||||
# we just need to subtract player pos and ball pos.
|
# we just need to subtract player pos and ball pos.
|
||||||
# Same logic as eric applied in Target Practice Gamemode.
|
# Same logic as eric applied in Target Practice Gamemode.
|
||||||
difference = ba.Vec3(target_player.position) - ba.Vec3(self.node.position)
|
difference = babase.Vec3(target_player.position) - babase.Vec3(self.node.position)
|
||||||
|
|
||||||
# discard Y position so ball shoot more straight.
|
# discard Y position so ball shoot more straight.
|
||||||
difference[1] = 0.0
|
difference[1] = 0.0
|
||||||
|
|
@ -301,7 +303,7 @@ class Box(ba.Actor):
|
||||||
difference[2] + self.player_facing_direction[1], # force direction Z
|
difference[2] + self.player_facing_direction[1], # force direction Z
|
||||||
)
|
)
|
||||||
# creating our timer and shoot the ball again.(and we create a loop)
|
# creating our timer and shoot the ball again.(and we create a loop)
|
||||||
self.shoot_timer = ba.Timer(self.shoot_speed, self.start_shoot)
|
self.shoot_timer = bs.Timer(self.shoot_speed, self.start_shoot)
|
||||||
|
|
||||||
def upgrade_ball_type(self, ball_type: BallType) -> NoReturn:
|
def upgrade_ball_type(self, ball_type: BallType) -> NoReturn:
|
||||||
|
|
||||||
|
|
@ -316,7 +318,7 @@ class Box(ba.Actor):
|
||||||
self.ball_mag = 3000
|
self.ball_mag = 3000
|
||||||
# box light color and ball tex
|
# box light color and ball tex
|
||||||
self.light.color = (1.0, 1.0, 0.0)
|
self.light.color = (1.0, 1.0, 0.0)
|
||||||
self.ball_tex = ba.gettexture('egg4')
|
self.ball_tex = bs.gettexture('egg4')
|
||||||
elif ball_type == BallType.MEDIUM:
|
elif ball_type == BallType.MEDIUM:
|
||||||
self.ball_mag = 3000
|
self.ball_mag = 3000
|
||||||
# decrease the gravity scale so, ball shoot without falling and straight.
|
# decrease the gravity scale so, ball shoot without falling and straight.
|
||||||
|
|
@ -325,7 +327,7 @@ class Box(ba.Actor):
|
||||||
self.shoot_speed = 0.4
|
self.shoot_speed = 0.4
|
||||||
# box light color and ball tex.
|
# box light color and ball tex.
|
||||||
self.light.color = (1.0, 0.0, 1.0)
|
self.light.color = (1.0, 0.0, 1.0)
|
||||||
self.ball_tex = ba.gettexture('egg3')
|
self.ball_tex = bs.gettexture('egg3')
|
||||||
elif ball_type == BallType.HARD:
|
elif ball_type == BallType.HARD:
|
||||||
self.ball_mag = 2500
|
self.ball_mag = 2500
|
||||||
self.ball_gravity = 0.0
|
self.ball_gravity = 0.0
|
||||||
|
|
@ -333,25 +335,26 @@ class Box(ba.Actor):
|
||||||
self.shoot_speed = 0.6
|
self.shoot_speed = 0.6
|
||||||
# box light color and ball tex.
|
# box light color and ball tex.
|
||||||
self.light.color = (1.0, 0.2, 1.0)
|
self.light.color = (1.0, 0.2, 1.0)
|
||||||
self.ball_tex = ba.gettexture('egg1')
|
self.ball_tex = bs.gettexture('egg1')
|
||||||
|
|
||||||
def shoot_animation(self) -> NoReturn:
|
def shoot_animation(self) -> NoReturn:
|
||||||
|
|
||||||
ba.animate(
|
bs.animate(
|
||||||
self.node,
|
self.node,
|
||||||
"model_scale", {
|
"mesh_scale", {
|
||||||
0.00: 1.4,
|
0.00: 1.4,
|
||||||
0.05: 1.7,
|
0.05: 1.7,
|
||||||
0.10: 1.4,
|
0.10: 1.4,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
# playing shoot sound.
|
# playing shoot sound.
|
||||||
ba.playsound(self.shoot_sound, position=self.node.position)
|
# self.shoot_sound, position = self.node.position.play();
|
||||||
|
self.shoot_sound.play()
|
||||||
|
|
||||||
def highlight_target_player(self, player: ba.Player) -> NoReturn:
|
def highlight_target_player(self, player: bs.Player) -> NoReturn:
|
||||||
|
|
||||||
# adding light
|
# adding light
|
||||||
light = ba.newnode(
|
light = bs.newnode(
|
||||||
"light",
|
"light",
|
||||||
owner=self.node,
|
owner=self.node,
|
||||||
attrs={
|
attrs={
|
||||||
|
|
@ -360,7 +363,7 @@ class Box(ba.Actor):
|
||||||
'color': (1.0, 0.0, 0.0),
|
'color': (1.0, 0.0, 0.0),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
ba.animate(
|
bs.animate(
|
||||||
light,
|
light,
|
||||||
"radius", {
|
"radius", {
|
||||||
0.05: 0.02,
|
0.05: 0.02,
|
||||||
|
|
@ -374,7 +377,7 @@ class Box(ba.Actor):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
# And a circle outline with ugly animation.
|
# And a circle outline with ugly animation.
|
||||||
circle_outline = ba.newnode(
|
circle_outline = bs.newnode(
|
||||||
"locator",
|
"locator",
|
||||||
owner=player.actor.node,
|
owner=player.actor.node,
|
||||||
attrs={
|
attrs={
|
||||||
|
|
@ -385,7 +388,7 @@ class Box(ba.Actor):
|
||||||
'additive': True,
|
'additive': True,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
ba.animate_array(
|
bs.animate_array(
|
||||||
circle_outline,
|
circle_outline,
|
||||||
'size',
|
'size',
|
||||||
1, {
|
1, {
|
||||||
|
|
@ -406,10 +409,10 @@ class Box(ba.Actor):
|
||||||
|
|
||||||
# immediately delete the node after another player has been targeted.
|
# immediately delete the node after another player has been targeted.
|
||||||
self.shoot_speed = 0.5 if self.shoot_speed == 0.0 else self.shoot_speed
|
self.shoot_speed = 0.5 if self.shoot_speed == 0.0 else self.shoot_speed
|
||||||
ba.timer(self.shoot_speed, light.delete)
|
bs.timer(self.shoot_speed, light.delete)
|
||||||
ba.timer(self.shoot_speed, circle_outline.delete)
|
bs.timer(self.shoot_speed, circle_outline.delete)
|
||||||
|
|
||||||
def calculate_player_analog_stick(self, player: ba.Player, distance: float) -> NoReturn:
|
def calculate_player_analog_stick(self, player: bs.Player, distance: float) -> NoReturn:
|
||||||
# at first i was very confused how i can read the player analog stick \
|
# at first i was very confused how i can read the player analog stick \
|
||||||
# then i saw TheMikirog#1984 autorun plugin code.
|
# then i saw TheMikirog#1984 autorun plugin code.
|
||||||
# and i got it how analog stick values are works.
|
# and i got it how analog stick values are works.
|
||||||
|
|
@ -461,48 +464,48 @@ class Box(ba.Actor):
|
||||||
self.shoot_timer = None
|
self.shoot_timer = None
|
||||||
|
|
||||||
|
|
||||||
class Player(ba.Player['Team']):
|
class Player(bs.Player['Team']):
|
||||||
"""Our player type for this game."""
|
"""Our player type for this game."""
|
||||||
|
|
||||||
|
|
||||||
class Team(ba.Team[Player]):
|
class Team(bs.Team[Player]):
|
||||||
"""Our team type for this game."""
|
"""Our team type for this game."""
|
||||||
|
|
||||||
# almost 80 % for game we done in box class.
|
# almost 80 % for game we done in box class.
|
||||||
# now remain things, like name, seetings, scoring, cooldonw,
|
# now remain things, like name, seetings, scoring, cooldonw,
|
||||||
# and main thing don't allow player to camp inside of box are going in this class.
|
# and main thing don't allow player to camp inside of box are going in this class.
|
||||||
|
|
||||||
# ba_meta export game
|
# ba_meta export bascenev1.GameActivity
|
||||||
|
|
||||||
|
|
||||||
class DodgeTheBall(ba.TeamGameActivity[Player, Team]):
|
class DodgeTheBall(bs.TeamGameActivity[Player, Team]):
|
||||||
|
|
||||||
# defining name, description and settings..
|
# defining name, description and settings..
|
||||||
name = 'Dodge the ball'
|
name = 'Dodge the ball'
|
||||||
description = 'Survive from shooting balls'
|
description = 'Survive from shooting balls'
|
||||||
|
|
||||||
available_settings = [
|
available_settings = [
|
||||||
ba.IntSetting(
|
bs.IntSetting(
|
||||||
'Cooldown',
|
'Cooldown',
|
||||||
min_value=20,
|
min_value=20,
|
||||||
default=45,
|
default=45,
|
||||||
increment=5,
|
increment=5,
|
||||||
),
|
),
|
||||||
ba.BoolSetting('Epic Mode', default=False)
|
bs.BoolSetting('Epic Mode', default=False)
|
||||||
]
|
]
|
||||||
|
|
||||||
# Don't allow joining after we start.
|
# Don't allow joining after we start.
|
||||||
allow_mid_activity_joins = False
|
allow_mid_activity_joins = False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def supports_session_type(cls, sessiontype: type[ba.Session]) -> bool:
|
def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool:
|
||||||
# We support team and ffa sessions.
|
# We support team and ffa sessions.
|
||||||
return issubclass(sessiontype, ba.FreeForAllSession) or issubclass(
|
return issubclass(sessiontype, bs.FreeForAllSession) or issubclass(
|
||||||
sessiontype, ba.DualTeamSession,
|
sessiontype, bs.DualTeamSession,
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_supported_maps(cls, sessiontype: type[ba.Session]) -> list[str]:
|
def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]:
|
||||||
# This Game mode need a flat and perfect shape map where can player fall outside map.
|
# This Game mode need a flat and perfect shape map where can player fall outside map.
|
||||||
# bombsquad have "Doom Shroom" map.
|
# bombsquad have "Doom Shroom" map.
|
||||||
# Not perfect map for this game mode but its fine for this gamemode.
|
# Not perfect map for this game mode but its fine for this gamemode.
|
||||||
|
|
@ -514,21 +517,21 @@ class DodgeTheBall(ba.TeamGameActivity[Player, Team]):
|
||||||
self._epic_mode = bool(settings['Epic Mode'])
|
self._epic_mode = bool(settings['Epic Mode'])
|
||||||
self.countdown_time = int(settings['Cooldown'])
|
self.countdown_time = int(settings['Cooldown'])
|
||||||
|
|
||||||
self.check_player_pos_timer: ba.Timer | None = None
|
self.check_player_pos_timer: bs.Timer | None = None
|
||||||
self.shield_drop_timer: ba.Timer | None = None
|
self.shield_drop_timer: bs.Timer | None = None
|
||||||
# cooldown and Box
|
# cooldown and Box
|
||||||
self._countdown: OnScreenCountdown | None = None
|
self._countdown: OnScreenCountdown | None = None
|
||||||
self.box: Box | None = None
|
self.box: Box | None = None
|
||||||
|
|
||||||
# this lists for scoring.
|
# this lists for scoring.
|
||||||
self.joined_player_list: list[ba.Player] = []
|
self.joined_player_list: list[bs.Player] = []
|
||||||
self.dead_player_list: list[ba.Player] = []
|
self.dead_player_list: list[bs.Player] = []
|
||||||
|
|
||||||
# normally play RUN AWAY music cause is match with our gamemode at.. my point,
|
# normally play RUN AWAY music cause is match with our gamemode at.. my point,
|
||||||
# but in epic switch to EPIC.
|
# but in epic switch to EPIC.
|
||||||
self.slow_motion = self._epic_mode
|
self.slow_motion = self._epic_mode
|
||||||
self.default_music = (
|
self.default_music = (
|
||||||
ba.MusicType.EPIC if self._epic_mode else ba.MusicType.RUN_AWAY
|
bs.MusicType.EPIC if self._epic_mode else bs.MusicType.RUN_AWAY
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_instance_description(self) -> str | Sequence:
|
def get_instance_description(self) -> str | Sequence:
|
||||||
|
|
@ -554,19 +557,19 @@ class DodgeTheBall(ba.TeamGameActivity[Player, Team]):
|
||||||
)
|
)
|
||||||
|
|
||||||
# and starts the cooldown and shootes.
|
# and starts the cooldown and shootes.
|
||||||
ba.timer(5.0, self._countdown.start)
|
bs.timer(5.0, self._countdown.start)
|
||||||
ba.timer(5.0, self.box.start_shoot)
|
bs.timer(5.0, self.box.start_shoot)
|
||||||
|
|
||||||
# start checking all player pos.
|
# start checking all player pos.
|
||||||
ba.timer(5.0, self.check_player_pos)
|
bs.timer(5.0, self.check_player_pos)
|
||||||
|
|
||||||
# drop shield every ten Seconds
|
# drop shield every ten Seconds
|
||||||
# need five seconds delay Because shootes start after 5 seconds.
|
# need five seconds delay Because shootes start after 5 seconds.
|
||||||
ba.timer(15.0, self.drop_shield)
|
bs.timer(15.0, self.drop_shield)
|
||||||
|
|
||||||
# This function returns all alive players in game.
|
# This function returns all alive players in game.
|
||||||
# i thinck you see this function in Box class.
|
# i thinck you see this function in Box class.
|
||||||
def get_alive_players(self) -> Sequence[ba.Player]:
|
def get_alive_players(self) -> Sequence[bs.Player]:
|
||||||
|
|
||||||
alive_players = []
|
alive_players = []
|
||||||
|
|
||||||
|
|
@ -583,7 +586,7 @@ class DodgeTheBall(ba.TeamGameActivity[Player, Team]):
|
||||||
for player in self.get_alive_players():
|
for player in self.get_alive_players():
|
||||||
|
|
||||||
# same logic as applied for the ball
|
# same logic as applied for the ball
|
||||||
difference = ba.Vec3(player.position) - ba.Vec3(self.box.node.position)
|
difference = babase.Vec3(player.position) - babase.Vec3(self.box.node.position)
|
||||||
|
|
||||||
distance = difference.length()
|
distance = difference.length()
|
||||||
|
|
||||||
|
|
@ -609,7 +612,7 @@ class DodgeTheBall(ba.TeamGameActivity[Player, Team]):
|
||||||
).autoretain()
|
).autoretain()
|
||||||
|
|
||||||
# create our timer and start looping it
|
# create our timer and start looping it
|
||||||
self.check_player_pos_timer = ba.Timer(0.1, self.check_player_pos)
|
self.check_player_pos_timer = bs.Timer(0.1, self.check_player_pos)
|
||||||
|
|
||||||
# drop useless shield's too give player temptation.
|
# drop useless shield's too give player temptation.
|
||||||
def drop_shield(self) -> NoReturn:
|
def drop_shield(self) -> NoReturn:
|
||||||
|
|
@ -626,7 +629,7 @@ class DodgeTheBall(ba.TeamGameActivity[Player, Team]):
|
||||||
poweruptype='shield',
|
poweruptype='shield',
|
||||||
).autoretain()
|
).autoretain()
|
||||||
|
|
||||||
self.shield_drop_timer = ba.Timer(10.0, self.drop_shield)
|
self.shield_drop_timer = bs.Timer(10.0, self.drop_shield)
|
||||||
|
|
||||||
# when cooldown time up i don't want that the game end immediately.
|
# when cooldown time up i don't want that the game end immediately.
|
||||||
def play_victory_sound_and_end(self) -> NoReturn:
|
def play_victory_sound_and_end(self) -> NoReturn:
|
||||||
|
|
@ -636,7 +639,7 @@ class DodgeTheBall(ba.TeamGameActivity[Player, Team]):
|
||||||
self.check_player_pos_timer = None
|
self.check_player_pos_timer = None
|
||||||
self.shield_drop_timer = None
|
self.shield_drop_timer = None
|
||||||
|
|
||||||
ba.timer(2.0, self.end_game)
|
bs.timer(2.0, self.end_game)
|
||||||
|
|
||||||
# this function runs when A player spawn in map
|
# this function runs when A player spawn in map
|
||||||
def spawn_player(self, player: Player) -> NoReturn:
|
def spawn_player(self, player: Player) -> NoReturn:
|
||||||
|
|
@ -682,7 +685,7 @@ class DodgeTheBall(ba.TeamGameActivity[Player, Team]):
|
||||||
# this gamemode needs to handle only one msg "PlayerDiedMessage".
|
# this gamemode needs to handle only one msg "PlayerDiedMessage".
|
||||||
def handlemessage(self, msg: Any) -> Any:
|
def handlemessage(self, msg: Any) -> Any:
|
||||||
|
|
||||||
if isinstance(msg, ba.PlayerDiedMessage):
|
if isinstance(msg, bs.PlayerDiedMessage):
|
||||||
|
|
||||||
# Augment standard behavior.
|
# Augment standard behavior.
|
||||||
super().handlemessage(msg)
|
super().handlemessage(msg)
|
||||||
|
|
@ -691,7 +694,7 @@ class DodgeTheBall(ba.TeamGameActivity[Player, Team]):
|
||||||
self.dead_player_list.append(msg.getplayer(Player))
|
self.dead_player_list.append(msg.getplayer(Player))
|
||||||
|
|
||||||
# check the end game.
|
# check the end game.
|
||||||
ba.timer(1.0, self._check_end_game)
|
bs.timer(1.0, self._check_end_game)
|
||||||
|
|
||||||
def end_game(self):
|
def end_game(self):
|
||||||
# kill timers
|
# kill timers
|
||||||
|
|
@ -736,7 +739,7 @@ class DodgeTheBall(ba.TeamGameActivity[Player, Team]):
|
||||||
|
|
||||||
# Ok now calc game results: set a score for each team and then tell \
|
# Ok now calc game results: set a score for each team and then tell \
|
||||||
# the game to end.
|
# the game to end.
|
||||||
results = ba.GameResults()
|
results = bs.GameResults()
|
||||||
|
|
||||||
# Remember that 'free-for-all' mode is simply a special form \
|
# Remember that 'free-for-all' mode is simply a special form \
|
||||||
# of 'teams' mode where each player gets their own team, so we can \
|
# of 'teams' mode where each player gets their own team, so we can \
|
||||||
|
|
|
||||||
18
plugins/minigames/frozen_one.py
Normal file
18
plugins/minigames/frozen_one.py
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Ported by your friend: Freaku
|
||||||
|
|
||||||
|
|
||||||
|
import babase
|
||||||
|
import bascenev1 as bs
|
||||||
|
from bascenev1lib.game.chosenone import Player, ChosenOneGame
|
||||||
|
|
||||||
|
|
||||||
|
# ba_meta require api 8
|
||||||
|
# ba_meta export bascenev1.GameActivity
|
||||||
|
class FrozenOneGame(ChosenOneGame):
|
||||||
|
name = 'Frozen One'
|
||||||
|
|
||||||
|
def _set_chosen_one_player(self, player: Player) -> None:
|
||||||
|
super()._set_chosen_one_player(player)
|
||||||
|
if hasattr(player, 'actor'):
|
||||||
|
player.actor.frozen = True
|
||||||
|
player.actor.node.frozen = 1
|
||||||
383
plugins/minigames/handball.py
Normal file
383
plugins/minigames/handball.py
Normal file
|
|
@ -0,0 +1,383 @@
|
||||||
|
# Released under the MIT License. See LICENSE for details.
|
||||||
|
#
|
||||||
|
"""Hockey game and support classes."""
|
||||||
|
|
||||||
|
# ba_meta require api 8
|
||||||
|
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
import babase
|
||||||
|
import bauiv1 as bui
|
||||||
|
import bascenev1 as bs
|
||||||
|
from bascenev1lib.actor.playerspaz import PlayerSpaz
|
||||||
|
from bascenev1lib.actor.scoreboard import Scoreboard
|
||||||
|
from bascenev1lib.actor.powerupbox import PowerupBoxFactory
|
||||||
|
from bascenev1lib.gameutils import SharedObjects
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from typing import Any, Sequence, Optional, Union
|
||||||
|
|
||||||
|
|
||||||
|
class PuckDiedMessage:
|
||||||
|
"""Inform something that a puck has died."""
|
||||||
|
|
||||||
|
def __init__(self, puck: Puck):
|
||||||
|
self.puck = puck
|
||||||
|
|
||||||
|
|
||||||
|
class Puck(bs.Actor):
|
||||||
|
"""A lovely giant hockey puck."""
|
||||||
|
|
||||||
|
def __init__(self, position: Sequence[float] = (0.0, 1.0, 0.0)):
|
||||||
|
super().__init__()
|
||||||
|
shared = SharedObjects.get()
|
||||||
|
activity = self.getactivity()
|
||||||
|
|
||||||
|
# Spawn just above the provided point.
|
||||||
|
self._spawn_pos = (position[0], position[1] + 1.0, position[2])
|
||||||
|
self.last_players_to_touch: dict[int, Player] = {}
|
||||||
|
self.scored = False
|
||||||
|
assert activity is not None
|
||||||
|
assert isinstance(activity, HockeyGame)
|
||||||
|
pmats = [shared.object_material, activity.puck_material]
|
||||||
|
self.node = bs.newnode('prop',
|
||||||
|
delegate=self,
|
||||||
|
attrs={
|
||||||
|
'mesh': activity.puck_mesh,
|
||||||
|
'color_texture': activity.puck_tex,
|
||||||
|
'body': 'sphere',
|
||||||
|
'reflection': 'soft',
|
||||||
|
'reflection_scale': [0.2],
|
||||||
|
'shadow_size': 0.8,
|
||||||
|
'is_area_of_interest': True,
|
||||||
|
'position': self._spawn_pos,
|
||||||
|
'materials': pmats
|
||||||
|
})
|
||||||
|
bs.animate(self.node, 'mesh_scale', {0: 0, 0.2: 1.3, 0.26: 1})
|
||||||
|
|
||||||
|
def handlemessage(self, msg: Any) -> Any:
|
||||||
|
if isinstance(msg, bs.DieMessage):
|
||||||
|
assert self.node
|
||||||
|
self.node.delete()
|
||||||
|
activity = self._activity()
|
||||||
|
if activity and not msg.immediate:
|
||||||
|
activity.handlemessage(PuckDiedMessage(self))
|
||||||
|
|
||||||
|
# If we go out of bounds, move back to where we started.
|
||||||
|
elif isinstance(msg, bs.OutOfBoundsMessage):
|
||||||
|
assert self.node
|
||||||
|
self.node.position = self._spawn_pos
|
||||||
|
|
||||||
|
elif isinstance(msg, bs.HitMessage):
|
||||||
|
assert self.node
|
||||||
|
assert msg.force_direction is not None
|
||||||
|
self.node.handlemessage(
|
||||||
|
'impulse', msg.pos[0], msg.pos[1], msg.pos[2], msg.velocity[0],
|
||||||
|
msg.velocity[1], msg.velocity[2], 1.0 * msg.magnitude,
|
||||||
|
1.0 * msg.velocity_magnitude, msg.radius, 0,
|
||||||
|
msg.force_direction[0], msg.force_direction[1],
|
||||||
|
msg.force_direction[2])
|
||||||
|
|
||||||
|
# If this hit came from a player, log them as the last to touch us.
|
||||||
|
s_player = msg.get_source_player(Player)
|
||||||
|
if s_player is not None:
|
||||||
|
activity = self._activity()
|
||||||
|
if activity:
|
||||||
|
if s_player in activity.players:
|
||||||
|
self.last_players_to_touch[s_player.team.id] = s_player
|
||||||
|
else:
|
||||||
|
super().handlemessage(msg)
|
||||||
|
|
||||||
|
|
||||||
|
class Player(bs.Player['Team']):
|
||||||
|
"""Our player type for this game."""
|
||||||
|
|
||||||
|
|
||||||
|
class Team(bs.Team[Player]):
|
||||||
|
"""Our team type for this game."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.score = 0
|
||||||
|
|
||||||
|
|
||||||
|
# ba_meta export bascenev1.GameActivity
|
||||||
|
class HockeyGame(bs.TeamGameActivity[Player, Team]):
|
||||||
|
"""Ice hockey game."""
|
||||||
|
|
||||||
|
name = 'Handball'
|
||||||
|
description = 'Score some goals.'
|
||||||
|
available_settings = [
|
||||||
|
bs.IntSetting(
|
||||||
|
'Score to Win',
|
||||||
|
min_value=1,
|
||||||
|
default=1,
|
||||||
|
increment=1,
|
||||||
|
),
|
||||||
|
bs.IntChoiceSetting(
|
||||||
|
'Time Limit',
|
||||||
|
choices=[
|
||||||
|
('None', 0),
|
||||||
|
('1 Minute', 60),
|
||||||
|
('2 Minutes', 120),
|
||||||
|
('5 Minutes', 300),
|
||||||
|
('10 Minutes', 600),
|
||||||
|
('20 Minutes', 1200),
|
||||||
|
],
|
||||||
|
default=0,
|
||||||
|
),
|
||||||
|
bs.FloatChoiceSetting(
|
||||||
|
'Respawn Times',
|
||||||
|
choices=[
|
||||||
|
('Shorter', 0.25),
|
||||||
|
('Short', 0.5),
|
||||||
|
('Normal', 1.0),
|
||||||
|
('Long', 2.0),
|
||||||
|
('Longer', 4.0),
|
||||||
|
],
|
||||||
|
default=1.0,
|
||||||
|
),
|
||||||
|
bs.BoolSetting('Epic Mode', default=False),
|
||||||
|
|
||||||
|
]
|
||||||
|
default_music = bs.MusicType.HOCKEY
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool:
|
||||||
|
return issubclass(sessiontype, bs.DualTeamSession)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]:
|
||||||
|
return bs.app.classic.getmaps('hockey')
|
||||||
|
|
||||||
|
def __init__(self, settings: dict):
|
||||||
|
super().__init__(settings)
|
||||||
|
shared = SharedObjects.get()
|
||||||
|
self._scoreboard = Scoreboard()
|
||||||
|
self._cheer_sound = bs.getsound('cheer')
|
||||||
|
self._chant_sound = bs.getsound('crowdChant')
|
||||||
|
self._foghorn_sound = bs.getsound('foghorn')
|
||||||
|
self._swipsound = bs.getsound('swip')
|
||||||
|
self._whistle_sound = bs.getsound('refWhistle')
|
||||||
|
self.puck_mesh = bs.getmesh('bomb')
|
||||||
|
self.puck_tex = bs.gettexture('bonesColor')
|
||||||
|
self._puck_sound = bs.getsound('metalHit')
|
||||||
|
self._epic_mode = bool(settings['Epic Mode'])
|
||||||
|
self.slow_motion = self._epic_mode
|
||||||
|
self.default_music = (bs.MusicType.EPIC
|
||||||
|
if self._epic_mode else bs.MusicType.FOOTBALL)
|
||||||
|
self.puck_material = bs.Material()
|
||||||
|
self.puck_material.add_actions(actions=(('modify_part_collision',
|
||||||
|
'friction', 0.5)))
|
||||||
|
self.puck_material.add_actions(conditions=('they_have_material',
|
||||||
|
shared.pickup_material),
|
||||||
|
actions=('modify_part_collision',
|
||||||
|
'collide', False))
|
||||||
|
self.puck_material = bs.Material()
|
||||||
|
self.puck_material.add_actions(actions=(('modify_part_collision',
|
||||||
|
'friction', 0.5)))
|
||||||
|
self.puck_material.add_actions(conditions=('they_have_material',
|
||||||
|
shared.pickup_material),
|
||||||
|
actions=('modify_part_collision',
|
||||||
|
'collide', True))
|
||||||
|
self.puck_material.add_actions(
|
||||||
|
conditions=(
|
||||||
|
('we_are_younger_than', 100),
|
||||||
|
'and',
|
||||||
|
('they_have_material', shared.object_material),
|
||||||
|
),
|
||||||
|
actions=('modify_node_collision', 'collide', False),
|
||||||
|
)
|
||||||
|
self.puck_material.add_actions(conditions=('they_have_material',
|
||||||
|
shared.footing_material),
|
||||||
|
actions=('impact_sound',
|
||||||
|
self._puck_sound, 0.2, 5))
|
||||||
|
|
||||||
|
# Keep track of which player last touched the puck
|
||||||
|
self.puck_material.add_actions(
|
||||||
|
conditions=('they_have_material', shared.player_material),
|
||||||
|
actions=(('call', 'at_connect',
|
||||||
|
self._handle_puck_player_collide), ))
|
||||||
|
|
||||||
|
# We want the puck to kill powerups; not get stopped by them
|
||||||
|
self.puck_material.add_actions(
|
||||||
|
conditions=('they_have_material',
|
||||||
|
PowerupBoxFactory.get().powerup_material),
|
||||||
|
actions=(('modify_part_collision', 'physical', False),
|
||||||
|
('message', 'their_node', 'at_connect', bs.DieMessage())))
|
||||||
|
self._score_region_material = bs.Material()
|
||||||
|
self._score_region_material.add_actions(
|
||||||
|
conditions=('they_have_material', self.puck_material),
|
||||||
|
actions=(('modify_part_collision', 'collide',
|
||||||
|
True), ('modify_part_collision', 'physical', False),
|
||||||
|
('call', 'at_connect', self._handle_score)))
|
||||||
|
self._puck_spawn_pos: Optional[Sequence[float]] = None
|
||||||
|
self._score_regions: Optional[list[bs.NodeActor]] = None
|
||||||
|
self._puck: Optional[Puck] = None
|
||||||
|
self._score_to_win = int(settings['Score to Win'])
|
||||||
|
self._time_limit = float(settings['Time Limit'])
|
||||||
|
|
||||||
|
def get_instance_description(self) -> Union[str, Sequence]:
|
||||||
|
if self._score_to_win == 1:
|
||||||
|
return 'Score a goal.'
|
||||||
|
return 'Score ${ARG1} goals.', self._score_to_win
|
||||||
|
|
||||||
|
def get_instance_description_short(self) -> Union[str, Sequence]:
|
||||||
|
if self._score_to_win == 1:
|
||||||
|
return 'score a goal'
|
||||||
|
return 'score ${ARG1} goals', self._score_to_win
|
||||||
|
|
||||||
|
def on_begin(self) -> None:
|
||||||
|
super().on_begin()
|
||||||
|
|
||||||
|
self.setup_standard_time_limit(self._time_limit)
|
||||||
|
self.setup_standard_powerup_drops()
|
||||||
|
self._puck_spawn_pos = self.map.get_flag_position(None)
|
||||||
|
self._spawn_puck()
|
||||||
|
|
||||||
|
# Set up the two score regions.
|
||||||
|
defs = self.map.defs
|
||||||
|
self._score_regions = []
|
||||||
|
self._score_regions.append(
|
||||||
|
bs.NodeActor(
|
||||||
|
bs.newnode('region',
|
||||||
|
attrs={
|
||||||
|
'position': defs.boxes['goal1'][0:3],
|
||||||
|
'scale': defs.boxes['goal1'][6:9],
|
||||||
|
'type': 'box',
|
||||||
|
'materials': [self._score_region_material]
|
||||||
|
})))
|
||||||
|
self._score_regions.append(
|
||||||
|
bs.NodeActor(
|
||||||
|
bs.newnode('region',
|
||||||
|
attrs={
|
||||||
|
'position': defs.boxes['goal2'][0:3],
|
||||||
|
'scale': defs.boxes['goal2'][6:9],
|
||||||
|
'type': 'box',
|
||||||
|
'materials': [self._score_region_material]
|
||||||
|
})))
|
||||||
|
self._update_scoreboard()
|
||||||
|
self._chant_sound.play()
|
||||||
|
|
||||||
|
def on_team_join(self, team: Team) -> None:
|
||||||
|
self._update_scoreboard()
|
||||||
|
|
||||||
|
def _handle_puck_player_collide(self) -> None:
|
||||||
|
collision = bs.getcollision()
|
||||||
|
try:
|
||||||
|
puck = collision.sourcenode.getdelegate(Puck, True)
|
||||||
|
player = collision.opposingnode.getdelegate(PlayerSpaz,
|
||||||
|
True).getplayer(
|
||||||
|
Player, True)
|
||||||
|
except bs.NotFoundError:
|
||||||
|
return
|
||||||
|
|
||||||
|
puck.last_players_to_touch[player.team.id] = player
|
||||||
|
|
||||||
|
def _kill_puck(self) -> None:
|
||||||
|
self._puck = None
|
||||||
|
|
||||||
|
def _handle_score(self) -> None:
|
||||||
|
"""A point has been scored."""
|
||||||
|
|
||||||
|
assert self._puck is not None
|
||||||
|
assert self._score_regions is not None
|
||||||
|
|
||||||
|
# Our puck might stick around for a second or two
|
||||||
|
# we don't want it to be able to score again.
|
||||||
|
if self._puck.scored:
|
||||||
|
return
|
||||||
|
|
||||||
|
region = bs.getcollision().sourcenode
|
||||||
|
index = 0
|
||||||
|
for index, score_region in enumerate(self._score_regions):
|
||||||
|
if region == score_region.node:
|
||||||
|
break
|
||||||
|
|
||||||
|
for team in self.teams:
|
||||||
|
if team.id == index:
|
||||||
|
scoring_team = team
|
||||||
|
team.score += 1
|
||||||
|
|
||||||
|
# Tell all players to celebrate.
|
||||||
|
for player in team.players:
|
||||||
|
if player.actor:
|
||||||
|
player.actor.handlemessage(bs.CelebrateMessage(2.0))
|
||||||
|
|
||||||
|
# If we've got the player from the scoring team that last
|
||||||
|
# touched us, give them points.
|
||||||
|
if (scoring_team.id in self._puck.last_players_to_touch
|
||||||
|
and self._puck.last_players_to_touch[scoring_team.id]):
|
||||||
|
self.stats.player_scored(
|
||||||
|
self._puck.last_players_to_touch[scoring_team.id],
|
||||||
|
100,
|
||||||
|
big_message=True)
|
||||||
|
|
||||||
|
# End game if we won.
|
||||||
|
if team.score >= self._score_to_win:
|
||||||
|
self.end_game()
|
||||||
|
|
||||||
|
self._foghorn_sound.play()
|
||||||
|
self._cheer_sound.play()
|
||||||
|
|
||||||
|
self._puck.scored = True
|
||||||
|
|
||||||
|
# Kill the puck (it'll respawn itself shortly).
|
||||||
|
bs.timer(1.0, self._kill_puck)
|
||||||
|
|
||||||
|
light = bs.newnode('light',
|
||||||
|
attrs={
|
||||||
|
'position': bs.getcollision().position,
|
||||||
|
'height_attenuated': False,
|
||||||
|
'color': (1, 0, 0)
|
||||||
|
})
|
||||||
|
bs.animate(light, 'intensity', {0: 0, 0.5: 1, 1.0: 0}, loop=True)
|
||||||
|
bs.timer(1.0, light.delete)
|
||||||
|
|
||||||
|
bs.cameraflash(duration=10.0)
|
||||||
|
self._update_scoreboard()
|
||||||
|
|
||||||
|
def end_game(self) -> None:
|
||||||
|
results = bs.GameResults()
|
||||||
|
for team in self.teams:
|
||||||
|
results.set_team_score(team, team.score)
|
||||||
|
self.end(results=results)
|
||||||
|
|
||||||
|
def _update_scoreboard(self) -> None:
|
||||||
|
winscore = self._score_to_win
|
||||||
|
for team in self.teams:
|
||||||
|
self._scoreboard.set_team_value(team, team.score, winscore)
|
||||||
|
|
||||||
|
def handlemessage(self, msg: Any) -> Any:
|
||||||
|
|
||||||
|
# Respawn dead players if they're still in the game.
|
||||||
|
if isinstance(msg, bs.PlayerDiedMessage):
|
||||||
|
# Augment standard behavior...
|
||||||
|
super().handlemessage(msg)
|
||||||
|
self.respawn_player(msg.getplayer(Player))
|
||||||
|
|
||||||
|
# Respawn dead pucks.
|
||||||
|
elif isinstance(msg, PuckDiedMessage):
|
||||||
|
if not self.has_ended():
|
||||||
|
bs.timer(3.0, self._spawn_puck)
|
||||||
|
else:
|
||||||
|
super().handlemessage(msg)
|
||||||
|
|
||||||
|
def _flash_puck_spawn(self) -> None:
|
||||||
|
light = bs.newnode('light',
|
||||||
|
attrs={
|
||||||
|
'position': self._puck_spawn_pos,
|
||||||
|
'height_attenuated': False,
|
||||||
|
'color': (1, 0, 0)
|
||||||
|
})
|
||||||
|
bs.animate(light, 'intensity', {0.0: 0, 0.25: 1, 0.5: 0}, loop=True)
|
||||||
|
bs.timer(1.0, light.delete)
|
||||||
|
|
||||||
|
def _spawn_puck(self) -> None:
|
||||||
|
self._swipsound.play()
|
||||||
|
self._whistle_sound.play()
|
||||||
|
self._flash_puck_spawn()
|
||||||
|
assert self._puck_spawn_pos is not None
|
||||||
|
self._puck = Puck(position=self._puck_spawn_pos)
|
||||||
48
plugins/minigames/icy_emits.py
Normal file
48
plugins/minigames/icy_emits.py
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
# Made by your friend: Freaku
|
||||||
|
|
||||||
|
|
||||||
|
import babase
|
||||||
|
import bascenev1 as bs
|
||||||
|
import random
|
||||||
|
from bascenev1lib.actor.bomb import Bomb
|
||||||
|
from bascenev1lib.game.meteorshower import Player, MeteorShowerGame
|
||||||
|
|
||||||
|
|
||||||
|
# ba_meta require api 8
|
||||||
|
# ba_meta export bascenev1.GameActivity
|
||||||
|
class IcyEmitsGame(MeteorShowerGame):
|
||||||
|
name = 'Icy Emits'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_supported_maps(cls, sessiontype):
|
||||||
|
return ['Lake Frigid', 'Hockey Stadium']
|
||||||
|
|
||||||
|
def _drop_bomb_cluster(self) -> None:
|
||||||
|
delay = 0.0
|
||||||
|
for _i in range(random.randrange(1, 3)):
|
||||||
|
# Drop them somewhere within our bounds with velocity pointing
|
||||||
|
# toward the opposite side.
|
||||||
|
pos = (-7.3 + 15.3 * random.random(), 5.3,
|
||||||
|
-5.5 + 2.1 * random.random())
|
||||||
|
dropdir = (-1.0 if pos[0] > 0 else 1.0)
|
||||||
|
vel = (0, 10, 0)
|
||||||
|
bs.timer(delay, babase.Call(self._drop_bomb, pos, vel))
|
||||||
|
delay += 0.1
|
||||||
|
self._set_meteor_timer()
|
||||||
|
|
||||||
|
def _drop_bomb(self, position, velocity):
|
||||||
|
random_xpositions = [-10, -9, -8, -7, -6, -5, -
|
||||||
|
4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||||
|
random_zpositions = [-5, -4.5, -4, -3.5, -3, -2.5, -2, -
|
||||||
|
1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5]
|
||||||
|
bomb_position = (random.choice(random_xpositions), 0.2, random.choice(random_zpositions))
|
||||||
|
Bomb(position=bomb_position, velocity=velocity, bomb_type='ice').autoretain()
|
||||||
|
|
||||||
|
|
||||||
|
# ba_meta export plugin
|
||||||
|
class byFreaku(babase.Plugin):
|
||||||
|
def __init__(self):
|
||||||
|
## Campaign support ##
|
||||||
|
randomPic = ['lakeFrigidPreview', 'hockeyStadiumPreview']
|
||||||
|
babase.app.classic.add_coop_practice_level(bs.Level(
|
||||||
|
name='Icy Emits', displayname='${GAME}', gametype=IcyEmitsGame, settings={}, preview_texture_name=random.choice(randomPic)))
|
||||||
|
|
@ -2,7 +2,7 @@ from __future__ import annotations
|
||||||
|
|
||||||
|
|
||||||
## Original creator: byANG3L ##
|
## Original creator: byANG3L ##
|
||||||
## Made by: Freaku / @[Just] Freak#4999 ##
|
## Made by: Freaku ##
|
||||||
|
|
||||||
## From: BSWorld Modpack (https://youtu.be/1TN56NLlShE) ##
|
## From: BSWorld Modpack (https://youtu.be/1TN56NLlShE) ##
|
||||||
|
|
||||||
|
|
@ -16,73 +16,63 @@ from __future__ import annotations
|
||||||
# def spawnAllMap(self)
|
# def spawnAllMap(self)
|
||||||
|
|
||||||
|
|
||||||
# ba_meta require api 7
|
# ba_meta require api 8
|
||||||
from typing import TYPE_CHECKING, overload
|
from typing import TYPE_CHECKING, overload
|
||||||
import _ba
|
import _babase
|
||||||
import ba
|
import babase
|
||||||
import random
|
import random
|
||||||
from bastd.gameutils import SharedObjects
|
import bascenev1 as bs
|
||||||
|
from bascenev1lib.gameutils import SharedObjects
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any, Sequence, Optional, List, Dict, Type, Union, Any, Literal
|
from typing import Any, Sequence, Optional, List, Dict, Type, Union, Any, Literal
|
||||||
|
|
||||||
|
|
||||||
class OnTimer(ba.Actor):
|
class OnTimer(bs.Actor):
|
||||||
"""Timer which counts but doesn't show on-screen"""
|
"""Timer which counts but doesn't show on-screen"""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._starttime_ms: Optional[int] = None
|
self._starttime_ms: int | None = None
|
||||||
self.node = ba.newnode('text', attrs={'v_attach': 'top', 'h_attach': 'center', 'h_align': 'center', 'color': (
|
self.node = bs.newnode('text', attrs={'v_attach': 'top', 'h_attach': 'center', 'h_align': 'center', 'color': (
|
||||||
1, 1, 0.5, 1), 'flatness': 0.5, 'shadow': 0.5, 'position': (0, -70), 'scale': 0, 'text': ''})
|
1, 1, 0.5, 1), 'flatness': 0.5, 'shadow': 0.5, 'position': (0, -70), 'scale': 0, 'text': ''})
|
||||||
self.inputnode = ba.newnode('timedisplay', attrs={
|
self.inputnode = bs.newnode(
|
||||||
'timemin': 0, 'showsubseconds': True})
|
'timedisplay', attrs={'timemin': 0, 'showsubseconds': True}
|
||||||
|
)
|
||||||
self.inputnode.connectattr('output', self.node, 'text')
|
self.inputnode.connectattr('output', self.node, 'text')
|
||||||
|
|
||||||
def start(self) -> None:
|
def start(self) -> None:
|
||||||
tval = ba.time(timeformat=ba.TimeFormat.MILLISECONDS)
|
"""Start the timer."""
|
||||||
|
tval = int(bs.time() * 1000.0)
|
||||||
assert isinstance(tval, int)
|
assert isinstance(tval, int)
|
||||||
self._starttime_ms = tval
|
self._starttime_ms = tval
|
||||||
self.inputnode.time1 = self._starttime_ms
|
self.inputnode.time1 = self._starttime_ms
|
||||||
ba.getactivity().globalsnode.connectattr('time', self.inputnode, 'time2')
|
bs.getactivity().globalsnode.connectattr(
|
||||||
|
'time', self.inputnode, 'time2'
|
||||||
|
)
|
||||||
|
|
||||||
def has_started(self) -> bool:
|
def has_started(self) -> bool:
|
||||||
|
"""Return whether this timer has started yet."""
|
||||||
return self._starttime_ms is not None
|
return self._starttime_ms is not None
|
||||||
|
|
||||||
def stop(self,
|
def stop(self, endtime: int | float | None = None) -> None:
|
||||||
endtime: Union[int, float] = None,
|
"""End the timer.
|
||||||
timeformat: ba.TimeFormat = ba.TimeFormat.SECONDS) -> None:
|
|
||||||
|
If 'endtime' is not None, it is used when calculating
|
||||||
|
the final display time; otherwise the current time is used.
|
||||||
|
"""
|
||||||
if endtime is None:
|
if endtime is None:
|
||||||
endtime = ba.time(timeformat=ba.TimeFormat.MILLISECONDS)
|
endtime = bs.time()
|
||||||
timeformat = ba.TimeFormat.MILLISECONDS
|
|
||||||
if self._starttime_ms is None:
|
if self._starttime_ms is None:
|
||||||
print('Warning: OnTimer.stop() called without start() first')
|
logging.warning(
|
||||||
|
'OnScreenTimer.stop() called without first calling start()'
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
endtime_ms: int
|
endtime_ms = int(endtime * 1000)
|
||||||
if timeformat is ba.TimeFormat.SECONDS:
|
|
||||||
endtime_ms = int(endtime * 1000)
|
|
||||||
elif timeformat is ba.TimeFormat.MILLISECONDS:
|
|
||||||
assert isinstance(endtime, int)
|
|
||||||
endtime_ms = endtime
|
|
||||||
else:
|
|
||||||
raise ValueError(f'invalid timeformat: {timeformat}')
|
|
||||||
|
|
||||||
self.inputnode.timemax = endtime_ms - self._starttime_ms
|
self.inputnode.timemax = endtime_ms - self._starttime_ms
|
||||||
# Overloads so type checker knows our exact return type based in args.
|
|
||||||
|
|
||||||
@overload
|
def getstarttime(self) -> float:
|
||||||
def getstarttime(self, timeformat: Literal[ba.TimeFormat.SECONDS] = ba.TimeFormat.SECONDS) -> float:
|
"""Return the scene-time when start() was called.
|
||||||
...
|
|
||||||
|
|
||||||
@overload
|
|
||||||
def getstarttime(self,
|
|
||||||
timeformat: Literal[ba.TimeFormat.MILLISECONDS]) -> int:
|
|
||||||
...
|
|
||||||
|
|
||||||
def getstarttime(
|
|
||||||
self,
|
|
||||||
timeformat: ba.TimeFormat = ba.TimeFormat.SECONDS
|
|
||||||
) -> Union[int, float]:
|
|
||||||
"""Return the sim-time when start() was called.
|
|
||||||
|
|
||||||
Time will be returned in seconds if timeformat is SECONDS or
|
Time will be returned in seconds if timeformat is SECONDS or
|
||||||
milliseconds if it is MILLISECONDS.
|
milliseconds if it is MILLISECONDS.
|
||||||
|
|
@ -90,15 +80,11 @@ class OnTimer(ba.Actor):
|
||||||
val_ms: Any
|
val_ms: Any
|
||||||
if self._starttime_ms is None:
|
if self._starttime_ms is None:
|
||||||
print('WARNING: getstarttime() called on un-started timer')
|
print('WARNING: getstarttime() called on un-started timer')
|
||||||
val_ms = ba.time(timeformat=ba.TimeFormat.MILLISECONDS)
|
val_ms = int(bs.time() * 1000.0)
|
||||||
else:
|
else:
|
||||||
val_ms = self._starttime_ms
|
val_ms = self._starttime_ms
|
||||||
assert isinstance(val_ms, int)
|
assert isinstance(val_ms, int)
|
||||||
if timeformat is ba.TimeFormat.SECONDS:
|
return 0.001 * val_ms
|
||||||
return 0.001 * val_ms
|
|
||||||
if timeformat is ba.TimeFormat.MILLISECONDS:
|
|
||||||
return val_ms
|
|
||||||
raise ValueError(f'invalid timeformat: {timeformat}')
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def starttime(self) -> float:
|
def starttime(self) -> float:
|
||||||
|
|
@ -107,12 +93,12 @@ class OnTimer(ba.Actor):
|
||||||
|
|
||||||
def handlemessage(self, msg: Any) -> Any:
|
def handlemessage(self, msg: Any) -> Any:
|
||||||
# if we're asked to die, just kill our node/timer
|
# if we're asked to die, just kill our node/timer
|
||||||
if isinstance(msg, ba.DieMessage):
|
if isinstance(msg, bs.DieMessage):
|
||||||
if self.node:
|
if self.node:
|
||||||
self.node.delete()
|
self.node.delete()
|
||||||
|
|
||||||
|
|
||||||
class Player(ba.Player['Team']):
|
class Player(bs.Player['Team']):
|
||||||
"""Our player type for this game."""
|
"""Our player type for this game."""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
|
|
@ -120,33 +106,33 @@ class Player(ba.Player['Team']):
|
||||||
self.death_time: Optional[float] = None
|
self.death_time: Optional[float] = None
|
||||||
|
|
||||||
|
|
||||||
class Team(ba.Team[Player]):
|
class Team(bs.Team[Player]):
|
||||||
"""Our team type for this game."""
|
"""Our team type for this game."""
|
||||||
|
|
||||||
|
|
||||||
# ba_meta export game
|
# ba_meta export bascenev1.GameActivity
|
||||||
class MGgame(ba.TeamGameActivity[Player, Team]):
|
class MGgame(bs.TeamGameActivity[Player, Team]):
|
||||||
|
|
||||||
name = 'Memory Game'
|
name = 'Memory Game'
|
||||||
description = 'Memories tiles and survive till the end!'
|
description = 'Memories tiles and survive till the end!'
|
||||||
available_settings = [ba.BoolSetting(
|
available_settings = [bs.BoolSetting(
|
||||||
'Epic Mode', default=False), ba.BoolSetting('Enable Bottom Credits', True)]
|
'Epic Mode', default=False), bs.BoolSetting('Enable Bottom Credits', True)]
|
||||||
scoreconfig = ba.ScoreConfig(label='Survived', scoretype=ba.ScoreType.MILLISECONDS, version='B')
|
scoreconfig = bs.ScoreConfig(label='Survived', scoretype=bs.ScoreType.MILLISECONDS, version='B')
|
||||||
|
|
||||||
# Print messages when players die (since its meaningful in this game).
|
# Print messages when players die (since its meaningful in this game).
|
||||||
announce_player_deaths = True
|
announce_player_deaths = True
|
||||||
|
|
||||||
# we're currently hard-coded for one map..
|
# we're currently hard-coded for one map..
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
|
def get_supported_maps(cls, sessiontype: Type[bs.Session]) -> List[str]:
|
||||||
return ['Sky Tiles']
|
return ['Sky Tiles']
|
||||||
|
|
||||||
# We support teams, free-for-all, and co-op sessions.
|
# We support teams, free-for-all, and co-op sessions.
|
||||||
@classmethod
|
@classmethod
|
||||||
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
|
def supports_session_type(cls, sessiontype: Type[bs.Session]) -> bool:
|
||||||
return (issubclass(sessiontype, ba.DualTeamSession)
|
return (issubclass(sessiontype, bs.DualTeamSession)
|
||||||
or issubclass(sessiontype, ba.FreeForAllSession)
|
or issubclass(sessiontype, bs.FreeForAllSession)
|
||||||
or issubclass(sessiontype, ba.CoopSession))
|
or issubclass(sessiontype, babase.CoopSession))
|
||||||
|
|
||||||
def __init__(self, settings: dict):
|
def __init__(self, settings: dict):
|
||||||
super().__init__(settings)
|
super().__init__(settings)
|
||||||
|
|
@ -157,14 +143,14 @@ class MGgame(ba.TeamGameActivity[Player, Team]):
|
||||||
self.credit_text = bool(settings['Enable Bottom Credits'])
|
self.credit_text = bool(settings['Enable Bottom Credits'])
|
||||||
|
|
||||||
# Some base class overrides:
|
# Some base class overrides:
|
||||||
self.default_music = (ba.MusicType.EPIC
|
self.default_music = (bs.MusicType.EPIC
|
||||||
if self._epic_mode else ba.MusicType.SURVIVAL)
|
if self._epic_mode else bs.MusicType.SURVIVAL)
|
||||||
if self._epic_mode:
|
if self._epic_mode:
|
||||||
self.slow_motion = True
|
self.slow_motion = True
|
||||||
shared = SharedObjects.get()
|
shared = SharedObjects.get()
|
||||||
self._collide_with_player = ba.Material()
|
self._collide_with_player = bs.Material()
|
||||||
self._collide_with_player.add_actions(actions=(('modify_part_collision', 'collide', True)))
|
self._collide_with_player.add_actions(actions=(('modify_part_collision', 'collide', True)))
|
||||||
self.dont_collide = ba.Material()
|
self.dont_collide = bs.Material()
|
||||||
self.dont_collide.add_actions(actions=(('modify_part_collision', 'collide', False)))
|
self.dont_collide.add_actions(actions=(('modify_part_collision', 'collide', False)))
|
||||||
self._levelStage = 0
|
self._levelStage = 0
|
||||||
|
|
||||||
|
|
@ -172,46 +158,46 @@ class MGgame(ba.TeamGameActivity[Player, Team]):
|
||||||
self._lastPlayerDeathTime = None
|
self._lastPlayerDeathTime = None
|
||||||
self._spawnCenter = (-3.17358, 2.75764, -2.99124)
|
self._spawnCenter = (-3.17358, 2.75764, -2.99124)
|
||||||
|
|
||||||
self._mapFGPModel = ba.getmodel('buttonSquareOpaque')
|
self._mapFGPModel = bs.getmesh('buttonSquareOpaque')
|
||||||
self._mapFGPDefaultTex = ba.gettexture('achievementOffYouGo')
|
self._mapFGPDefaultTex = bs.gettexture('achievementOffYouGo')
|
||||||
|
|
||||||
self._mapFGCurseTex = ba.gettexture('powerupCurse')
|
self._mapFGCurseTex = bs.gettexture('powerupCurse')
|
||||||
self._mapFGHealthTex = ba.gettexture('powerupHealth')
|
self._mapFGHealthTex = bs.gettexture('powerupHealth')
|
||||||
self._mapFGIceTex = ba.gettexture('powerupIceBombs')
|
self._mapFGIceTex = bs.gettexture('powerupIceBombs')
|
||||||
self._mapFGImpactTex = ba.gettexture('powerupImpactBombs')
|
self._mapFGImpactTex = bs.gettexture('powerupImpactBombs')
|
||||||
self._mapFGMinesTex = ba.gettexture('powerupLandMines')
|
self._mapFGMinesTex = bs.gettexture('powerupLandMines')
|
||||||
self._mapFGPunchTex = ba.gettexture('powerupPunch')
|
self._mapFGPunchTex = bs.gettexture('powerupPunch')
|
||||||
self._mapFGShieldTex = ba.gettexture('powerupShield')
|
self._mapFGShieldTex = bs.gettexture('powerupShield')
|
||||||
self._mapFGStickyTex = ba.gettexture('powerupStickyBombs')
|
self._mapFGStickyTex = bs.gettexture('powerupStickyBombs')
|
||||||
|
|
||||||
self._mapFGSpaz = ba.gettexture('neoSpazIcon')
|
self._mapFGSpaz = bs.gettexture('neoSpazIcon')
|
||||||
self._mapFGZoe = ba.gettexture('zoeIcon')
|
self._mapFGZoe = bs.gettexture('zoeIcon')
|
||||||
self._mapFGSnake = ba.gettexture('ninjaIcon')
|
self._mapFGSnake = bs.gettexture('ninjaIcon')
|
||||||
self._mapFGKronk = ba.gettexture('kronkIcon')
|
self._mapFGKronk = bs.gettexture('kronkIcon')
|
||||||
self._mapFGMel = ba.gettexture('melIcon')
|
self._mapFGMel = bs.gettexture('melIcon')
|
||||||
self._mapFGJack = ba.gettexture('jackIcon')
|
self._mapFGJack = bs.gettexture('jackIcon')
|
||||||
self._mapFGSanta = ba.gettexture('santaIcon')
|
self._mapFGSanta = bs.gettexture('santaIcon')
|
||||||
self._mapFGFrosty = ba.gettexture('frostyIcon')
|
self._mapFGFrosty = bs.gettexture('frostyIcon')
|
||||||
self._mapFGBones = ba.gettexture('bonesIcon')
|
self._mapFGBones = bs.gettexture('bonesIcon')
|
||||||
self._mapFGBernard = ba.gettexture('bearIcon')
|
self._mapFGBernard = bs.gettexture('bearIcon')
|
||||||
self._mapFGPascal = ba.gettexture('penguinIcon')
|
self._mapFGPascal = bs.gettexture('penguinIcon')
|
||||||
self._mapFGAli = ba.gettexture('aliIcon')
|
self._mapFGAli = bs.gettexture('aliIcon')
|
||||||
self._mapFGRobot = ba.gettexture('cyborgIcon')
|
self._mapFGRobot = bs.gettexture('cyborgIcon')
|
||||||
self._mapFGAgent = ba.gettexture('agentIcon')
|
self._mapFGAgent = bs.gettexture('agentIcon')
|
||||||
self._mapFGGrumbledorf = ba.gettexture('wizardIcon')
|
self._mapFGGrumbledorf = bs.gettexture('wizardIcon')
|
||||||
self._mapFGPixel = ba.gettexture('pixieIcon')
|
self._mapFGPixel = bs.gettexture('pixieIcon')
|
||||||
|
|
||||||
self._imageTextDefault = ba.gettexture('bg')
|
self._imageTextDefault = bs.gettexture('bg')
|
||||||
self._circleTex = ba.gettexture('circleShadow')
|
self._circleTex = bs.gettexture('circleShadow')
|
||||||
|
|
||||||
self._image = ba.newnode('image',
|
self._image = bs.newnode('image',
|
||||||
attrs={'texture': self._imageTextDefault,
|
attrs={'texture': self._imageTextDefault,
|
||||||
'position': (0, -100),
|
'position': (0, -100),
|
||||||
'scale': (100, 100),
|
'scale': (100, 100),
|
||||||
'opacity': 0.0,
|
'opacity': 0.0,
|
||||||
'attach': 'topCenter'})
|
'attach': 'topCenter'})
|
||||||
|
|
||||||
self._textCounter = ba.newnode('text',
|
self._textCounter = bs.newnode('text',
|
||||||
attrs={'text': '10',
|
attrs={'text': '10',
|
||||||
'position': (0, -100),
|
'position': (0, -100),
|
||||||
'scale': 2.3,
|
'scale': 2.3,
|
||||||
|
|
@ -223,7 +209,7 @@ class MGgame(ba.TeamGameActivity[Player, Team]):
|
||||||
'h_align': 'center',
|
'h_align': 'center',
|
||||||
'v_align': 'center'})
|
'v_align': 'center'})
|
||||||
|
|
||||||
self._textLevel = ba.newnode('text',
|
self._textLevel = bs.newnode('text',
|
||||||
attrs={'text': 'Level ' + str(self._levelStage),
|
attrs={'text': 'Level ' + str(self._levelStage),
|
||||||
'position': (0, -28),
|
'position': (0, -28),
|
||||||
'scale': 1.3,
|
'scale': 1.3,
|
||||||
|
|
@ -236,21 +222,21 @@ class MGgame(ba.TeamGameActivity[Player, Team]):
|
||||||
'h_align': 'center',
|
'h_align': 'center',
|
||||||
'v_align': 'center'})
|
'v_align': 'center'})
|
||||||
|
|
||||||
self._imageCircle = ba.newnode('image',
|
self._imageCircle = bs.newnode('image',
|
||||||
attrs={'texture': self._circleTex,
|
attrs={'texture': self._circleTex,
|
||||||
'position': (75, -75),
|
'position': (75, -75),
|
||||||
'scale': (20, 20),
|
'scale': (20, 20),
|
||||||
'color': (0.2, 0.2, 0.2),
|
'color': (0.2, 0.2, 0.2),
|
||||||
'opacity': 0.0,
|
'opacity': 0.0,
|
||||||
'attach': 'topCenter'})
|
'attach': 'topCenter'})
|
||||||
self._imageCircle2 = ba.newnode('image',
|
self._imageCircle2 = bs.newnode('image',
|
||||||
attrs={'texture': self._circleTex,
|
attrs={'texture': self._circleTex,
|
||||||
'position': (75, -100),
|
'position': (75, -100),
|
||||||
'scale': (20, 20),
|
'scale': (20, 20),
|
||||||
'color': (0.2, 0.2, 0.2),
|
'color': (0.2, 0.2, 0.2),
|
||||||
'opacity': 0.0,
|
'opacity': 0.0,
|
||||||
'attach': 'topCenter'})
|
'attach': 'topCenter'})
|
||||||
self._imageCircle3 = ba.newnode('image',
|
self._imageCircle3 = bs.newnode('image',
|
||||||
attrs={'texture': self._circleTex,
|
attrs={'texture': self._circleTex,
|
||||||
'position': (75, -125),
|
'position': (75, -125),
|
||||||
'scale': (20, 20),
|
'scale': (20, 20),
|
||||||
|
|
@ -260,12 +246,12 @@ class MGgame(ba.TeamGameActivity[Player, Team]):
|
||||||
|
|
||||||
def on_transition_in(self) -> None:
|
def on_transition_in(self) -> None:
|
||||||
super().on_transition_in()
|
super().on_transition_in()
|
||||||
self._bellLow = ba.getsound('bellLow')
|
self._bellLow = bs.getsound('bellLow')
|
||||||
self._bellMed = ba.getsound('bellMed')
|
self._bellMed = bs.getsound('bellMed')
|
||||||
self._bellHigh = ba.getsound('bellHigh')
|
self._bellHigh = bs.getsound('bellHigh')
|
||||||
self._tickSound = ba.getsound('tick')
|
self._tickSound = bs.getsound('tick')
|
||||||
self._tickFinal = ba.getsound('powerup01')
|
self._tickFinal = bs.getsound('powerup01')
|
||||||
self._scoreSound = ba.getsound('score')
|
self._scoreSound = bs.getsound('score')
|
||||||
|
|
||||||
self._image.opacity = 1
|
self._image.opacity = 1
|
||||||
self._textCounter.opacity = 1
|
self._textCounter.opacity = 1
|
||||||
|
|
@ -282,8 +268,8 @@ class MGgame(ba.TeamGameActivity[Player, Team]):
|
||||||
|
|
||||||
if self._levelStage == 1:
|
if self._levelStage == 1:
|
||||||
timeStart = 6
|
timeStart = 6
|
||||||
ba.timer(timeStart, self._randomPlatform)
|
bs.timer(timeStart, self._randomPlatform)
|
||||||
ba.timer(timeStart, self.startCounter)
|
bs.timer(timeStart, self.startCounter)
|
||||||
|
|
||||||
def on_begin(self) -> None:
|
def on_begin(self) -> None:
|
||||||
super().on_begin()
|
super().on_begin()
|
||||||
|
|
@ -308,7 +294,7 @@ class MGgame(ba.TeamGameActivity[Player, Team]):
|
||||||
self.coldel15 = True
|
self.coldel15 = True
|
||||||
self.coldel16 = True
|
self.coldel16 = True
|
||||||
if self.credit_text:
|
if self.credit_text:
|
||||||
t = ba.newnode('text',
|
t = bs.newnode('text',
|
||||||
attrs={'text': "Made by Freaku\nOriginally for 1.4: byANG3L", # Disable 'Enable Bottom Credits' when making playlist, No need to edit this lovely...
|
attrs={'text': "Made by Freaku\nOriginally for 1.4: byANG3L", # Disable 'Enable Bottom Credits' when making playlist, No need to edit this lovely...
|
||||||
'scale': 0.7,
|
'scale': 0.7,
|
||||||
'position': (0, 0),
|
'position': (0, 0),
|
||||||
|
|
@ -317,13 +303,13 @@ class MGgame(ba.TeamGameActivity[Player, Team]):
|
||||||
'color': (1, 1, 1),
|
'color': (1, 1, 1),
|
||||||
'h_align': 'center',
|
'h_align': 'center',
|
||||||
'v_attach': 'bottom'})
|
'v_attach': 'bottom'})
|
||||||
self.spawnAllMap()
|
self.spawnAllMap()
|
||||||
self.flashHide()
|
self.flashHide()
|
||||||
|
|
||||||
# Check for immediate end (if we've only got 1 player, etc).
|
# Check for immediate end (if we've only got 1 player, etc).
|
||||||
ba.timer(5, self._check_end_game)
|
bs.timer(5, self._check_end_game)
|
||||||
self._dingSound = ba.getsound('dingSmall')
|
self._dingSound = bs.getsound('dingSmall')
|
||||||
self._dingSoundHigh = ba.getsound('dingSmallHigh')
|
self._dingSoundHigh = bs.getsound('dingSmallHigh')
|
||||||
|
|
||||||
def startCounter(self):
|
def startCounter(self):
|
||||||
self._textCounter.text = '10'
|
self._textCounter.text = '10'
|
||||||
|
|
@ -339,44 +325,44 @@ class MGgame(ba.TeamGameActivity[Player, Team]):
|
||||||
def count1():
|
def count1():
|
||||||
def countFinal():
|
def countFinal():
|
||||||
self._textCounter.text = ''
|
self._textCounter.text = ''
|
||||||
ba.playsound(self._tickFinal)
|
self._tickFinal.play()
|
||||||
self._stop()
|
self._stop()
|
||||||
self._textCounter.text = '1'
|
self._textCounter.text = '1'
|
||||||
ba.playsound(self._tickSound)
|
self._tickSound.play()
|
||||||
ba.timer(1, countFinal)
|
bs.timer(1, countFinal)
|
||||||
self._textCounter.text = '2'
|
self._textCounter.text = '2'
|
||||||
ba.playsound(self._tickSound)
|
self._tickSound.play()
|
||||||
ba.timer(1, count1)
|
bs.timer(1, count1)
|
||||||
self._textCounter.text = '3'
|
self._textCounter.text = '3'
|
||||||
ba.playsound(self._tickSound)
|
self._tickSound.play()
|
||||||
ba.timer(1, count2)
|
bs.timer(1, count2)
|
||||||
self._textCounter.text = '4'
|
self._textCounter.text = '4'
|
||||||
ba.playsound(self._tickSound)
|
self._tickSound.play()
|
||||||
ba.timer(1, count3)
|
bs.timer(1, count3)
|
||||||
self._textCounter.text = '5'
|
self._textCounter.text = '5'
|
||||||
ba.playsound(self._tickSound)
|
self._tickSound.play()
|
||||||
ba.timer(1, count4)
|
bs.timer(1, count4)
|
||||||
self._textCounter.text = '6'
|
self._textCounter.text = '6'
|
||||||
ba.playsound(self._tickSound)
|
self._tickSound.play()
|
||||||
ba.timer(1, count5)
|
bs.timer(1, count5)
|
||||||
self._textCounter.text = '7'
|
self._textCounter.text = '7'
|
||||||
ba.playsound(self._tickSound)
|
self._tickSound.play()
|
||||||
ba.timer(1, count6)
|
bs.timer(1, count6)
|
||||||
self._textCounter.text = '8'
|
self._textCounter.text = '8'
|
||||||
ba.playsound(self._tickSound)
|
self._tickSound.play()
|
||||||
ba.timer(1, count7)
|
bs.timer(1, count7)
|
||||||
self._textCounter.text = '9'
|
self._textCounter.text = '9'
|
||||||
ba.playsound(self._tickSound)
|
self._tickSound.play()
|
||||||
ba.timer(1, count8)
|
bs.timer(1, count8)
|
||||||
ba.timer(1, count9)
|
bs.timer(1, count9)
|
||||||
|
|
||||||
def on_player_join(self, player: Player) -> None:
|
def on_player_join(self, player: Player) -> None:
|
||||||
# Don't allow joining after we start
|
# Don't allow joining after we start
|
||||||
# (would enable leave/rejoin tomfoolery).
|
# (would enable leave/rejoin tomfoolery).
|
||||||
if self.has_begun():
|
if self.has_begun():
|
||||||
ba.screenmessage(
|
bs.broadcastmessage(
|
||||||
ba.Lstr(resource='playerDelayedJoinText',
|
babase.Lstr(resource='playerDelayedJoinText',
|
||||||
subs=[('${PLAYER}', player.getname(full=True))]),
|
subs=[('${PLAYER}', player.getname(full=True))]),
|
||||||
color=(0, 1, 0), transient=True, clients=[player.sessionplayer.inputdevice.client_id])
|
color=(0, 1, 0), transient=True, clients=[player.sessionplayer.inputdevice.client_id])
|
||||||
# For score purposes, mark them as having died right as the
|
# For score purposes, mark them as having died right as the
|
||||||
# game started.
|
# game started.
|
||||||
|
|
@ -393,12 +379,12 @@ class MGgame(ba.TeamGameActivity[Player, Team]):
|
||||||
self._check_end_game()
|
self._check_end_game()
|
||||||
|
|
||||||
# overriding the default character spawning..
|
# overriding the default character spawning..
|
||||||
def spawn_player(self, player: Player) -> ba.Actor:
|
def spawn_player(self, player: Player) -> bs.Actor:
|
||||||
spaz = self.spawn_player_spaz(player)
|
spaz = self.spawn_player_spaz(player)
|
||||||
pos = (self._spawnCenter[0] + random.uniform(-1.5, 2.5),
|
pos = (self._spawnCenter[0] + random.uniform(-1.5, 2.5),
|
||||||
self._spawnCenter[1], self._spawnCenter[2] + random.uniform(-2.5, 1.5))
|
self._spawnCenter[1], self._spawnCenter[2] + random.uniform(-2.5, 1.5))
|
||||||
spaz.connect_controls_to_player(enable_punch=False, enable_bomb=False, enable_pickup=False)
|
spaz.connect_controls_to_player(enable_punch=False, enable_bomb=False, enable_pickup=False)
|
||||||
spaz.handlemessage(ba.StandMessage(pos))
|
spaz.handlemessage(bs.StandMessage(pos))
|
||||||
return spaz
|
return spaz
|
||||||
|
|
||||||
def _randomSelect(self):
|
def _randomSelect(self):
|
||||||
|
|
@ -453,17 +439,17 @@ class MGgame(ba.TeamGameActivity[Player, Team]):
|
||||||
def circle3():
|
def circle3():
|
||||||
self._imageCircle3.color = (0.0, 1.0, 0.0)
|
self._imageCircle3.color = (0.0, 1.0, 0.0)
|
||||||
self._imageCircle3.opacity = 1.0
|
self._imageCircle3.opacity = 1.0
|
||||||
ba.playsound(self._bellHigh)
|
self._bellHigh.play()
|
||||||
ba.timer(0.2, self._doDelete)
|
bs.timer(0.2, self._doDelete)
|
||||||
self._imageCircle2.color = (1.0, 1.0, 0.0)
|
self._imageCircle2.color = (1.0, 1.0, 0.0)
|
||||||
self._imageCircle2.opacity = 1.0
|
self._imageCircle2.opacity = 1.0
|
||||||
ba.playsound(self._bellMed)
|
self._bellMed.play()
|
||||||
ba.timer(1, circle3)
|
bs.timer(1, circle3)
|
||||||
self._imageCircle.color = (1.0, 0.0, 0.0)
|
self._imageCircle.color = (1.0, 0.0, 0.0)
|
||||||
self._imageCircle.opacity = 1.0
|
self._imageCircle.opacity = 1.0
|
||||||
ba.playsound(self._bellLow)
|
self._bellLow.play()
|
||||||
ba.timer(1, circle2)
|
bs.timer(1, circle2)
|
||||||
ba.timer(1, circle)
|
bs.timer(1, circle)
|
||||||
|
|
||||||
def _randomPlatform(self):
|
def _randomPlatform(self):
|
||||||
if self._levelStage == 1:
|
if self._levelStage == 1:
|
||||||
|
|
@ -564,13 +550,13 @@ class MGgame(ba.TeamGameActivity[Player, Team]):
|
||||||
self._mixPlatform()
|
self._mixPlatform()
|
||||||
|
|
||||||
def _mixPlatform(self):
|
def _mixPlatform(self):
|
||||||
ba.timer(1, self.flashShow)
|
bs.timer(1, self.flashShow)
|
||||||
ba.timer(3, self.flashHide)
|
bs.timer(3, self.flashHide)
|
||||||
ba.timer(4, self.flashShow)
|
bs.timer(4, self.flashShow)
|
||||||
ba.timer(6, self.flashHide)
|
bs.timer(6, self.flashHide)
|
||||||
ba.timer(7, self.flashShow)
|
bs.timer(7, self.flashShow)
|
||||||
ba.timer(9, self.flashHide)
|
bs.timer(9, self.flashHide)
|
||||||
ba.timer(13.2, self.flashShow)
|
bs.timer(13.2, self.flashShow)
|
||||||
|
|
||||||
def flashHide(self):
|
def flashHide(self):
|
||||||
self.mapFGP.color_texture = self._mapFGPDefaultTex
|
self.mapFGP.color_texture = self._mapFGPDefaultTex
|
||||||
|
|
@ -674,14 +660,14 @@ class MGgame(ba.TeamGameActivity[Player, Team]):
|
||||||
self.mapFGP16col.delete()
|
self.mapFGP16col.delete()
|
||||||
self.coldel16 = True
|
self.coldel16 = True
|
||||||
|
|
||||||
ba.timer(3.3, self._platformTexDefault)
|
bs.timer(3.3, self._platformTexDefault)
|
||||||
|
|
||||||
def spawnAllMap(self):
|
def spawnAllMap(self):
|
||||||
"""
|
"""
|
||||||
# Here's how it works:
|
# Here's how it works:
|
||||||
# First, create prop with a gravity scale of 0
|
# First, create prop with a gravity scale of 0
|
||||||
# Then use a in-game model which will suit it (For this one I didn't chose box, since it will look kinda weird) Right?
|
# Then use a in-game mesh which will suit it (For this one I didn't chose box, since it will look kinda weird) Right?
|
||||||
# Instead I used a 2d model (which is nothing but a button in menu)
|
# Instead I used a 2d mesh (which is nothing but a button in menu)
|
||||||
# This prop SHOULD NOT collide with anything, since it has gravity_scale of 0 if it'll get weight it will fall down :((
|
# This prop SHOULD NOT collide with anything, since it has gravity_scale of 0 if it'll get weight it will fall down :((
|
||||||
# These are where we change those color-textures and is seen in-game
|
# These are where we change those color-textures and is seen in-game
|
||||||
|
|
||||||
|
|
@ -696,130 +682,130 @@ class MGgame(ba.TeamGameActivity[Player, Team]):
|
||||||
"""
|
"""
|
||||||
shared = SharedObjects.get()
|
shared = SharedObjects.get()
|
||||||
if self.coldel:
|
if self.coldel:
|
||||||
self.mapFGP = ba.newnode('prop',
|
self.mapFGP = bs.newnode('prop',
|
||||||
attrs={'body': 'puck', 'position': (3, 2, -9), 'model': self._mapFGPModel, 'model_scale': 3.8, 'body_scale': 3.8, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
attrs={'body': 'puck', 'position': (4.5, 2, -9), 'mesh': self._mapFGPModel, 'mesh_scale': 3.73, 'body_scale': 3.73, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
||||||
self.mapFGPTex = None
|
self.mapFGPTex = None
|
||||||
self.mapFGPcol = ba.newnode('region', attrs={'position': (3, 2, -9), 'scale': (
|
self.mapFGPcol = bs.newnode('region', attrs={'position': (4.5, 2, -9), 'scale': (
|
||||||
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
||||||
self.coldel = False
|
self.coldel = False
|
||||||
|
|
||||||
if self.coldel2:
|
if self.coldel2:
|
||||||
self.mapFGP2 = ba.newnode('prop',
|
self.mapFGP2 = bs.newnode('prop',
|
||||||
attrs={'body': 'puck', 'position': (3, 2, -6), 'model': self._mapFGPModel, 'model_scale': 3.8, 'body_scale': 3.8, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
attrs={'body': 'puck', 'position': (4.5, 2, -6), 'mesh': self._mapFGPModel, 'mesh_scale': 3.73, 'body_scale': 3.73, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
||||||
self.mapFGP2Tex = None
|
self.mapFGP2Tex = None
|
||||||
self.mapFGP2col = ba.newnode('region', attrs={'position': (3, 2, -6), 'scale': (
|
self.mapFGP2col = bs.newnode('region', attrs={'position': (4.5, 2, -6), 'scale': (
|
||||||
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
||||||
self.coldel2 = False
|
self.coldel2 = False
|
||||||
|
|
||||||
if self.coldel3:
|
if self.coldel3:
|
||||||
self.mapFGP3 = ba.newnode('prop',
|
self.mapFGP3 = bs.newnode('prop',
|
||||||
attrs={'body': 'puck', 'position': (3, 2, -3), 'model': self._mapFGPModel, 'model_scale': 3.8, 'body_scale': 3.8, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
attrs={'body': 'puck', 'position': (4.5, 2, -3), 'mesh': self._mapFGPModel, 'mesh_scale': 3.73, 'body_scale': 3.73, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
||||||
self.mapFGP3Tex = None
|
self.mapFGP3Tex = None
|
||||||
self.mapFGP3col = ba.newnode('region', attrs={'position': (3, 2, -3), 'scale': (
|
self.mapFGP3col = bs.newnode('region', attrs={'position': (4.5, 2, -3), 'scale': (
|
||||||
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
||||||
self.coldel3 = False
|
self.coldel3 = False
|
||||||
|
|
||||||
if self.coldel4:
|
if self.coldel4:
|
||||||
self.mapFGP4 = ba.newnode('prop',
|
self.mapFGP4 = bs.newnode('prop',
|
||||||
attrs={'body': 'puck', 'position': (3, 2, 0), 'model': self._mapFGPModel, 'model_scale': 3.8, 'body_scale': 3.8, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
attrs={'body': 'puck', 'position': (4.5, 2, 0), 'mesh': self._mapFGPModel, 'mesh_scale': 3.73, 'body_scale': 3.73, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
||||||
self.mapFGP4Tex = None
|
self.mapFGP4Tex = None
|
||||||
self.mapFGP4col = ba.newnode('region', attrs={'position': (3, 2, 0), 'scale': (
|
self.mapFGP4col = bs.newnode('region', attrs={'position': (4.5, 2, 0), 'scale': (
|
||||||
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
||||||
self.coldel4 = False
|
self.coldel4 = False
|
||||||
|
|
||||||
if self.coldel5:
|
if self.coldel5:
|
||||||
self.mapFGP5 = ba.newnode('prop',
|
self.mapFGP5 = bs.newnode('prop',
|
||||||
attrs={'body': 'puck', 'position': (0, 2, -9), 'model': self._mapFGPModel, 'model_scale': 3.8, 'body_scale': 3.8, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
attrs={'body': 'puck', 'position': (1.5, 2, -9), 'mesh': self._mapFGPModel, 'mesh_scale': 3.73, 'body_scale': 3.73, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
||||||
self.mapFGP5Tex = None
|
self.mapFGP5Tex = None
|
||||||
self.mapFGP5col = ba.newnode('region', attrs={'position': (0, 2, -9), 'scale': (
|
self.mapFGP5col = bs.newnode('region', attrs={'position': (1.5, 2, -9), 'scale': (
|
||||||
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
||||||
self.coldel5 = False
|
self.coldel5 = False
|
||||||
|
|
||||||
if self.coldel6:
|
if self.coldel6:
|
||||||
self.mapFGP6 = ba.newnode('prop',
|
self.mapFGP6 = bs.newnode('prop',
|
||||||
attrs={'body': 'puck', 'position': (0, 2, -6), 'model': self._mapFGPModel, 'model_scale': 3.8, 'body_scale': 3.8, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
attrs={'body': 'puck', 'position': (1.5, 2, -6), 'mesh': self._mapFGPModel, 'mesh_scale': 3.73, 'body_scale': 3.73, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
||||||
self.mapFGP6Tex = None
|
self.mapFGP6Tex = None
|
||||||
self.mapFGP6col = ba.newnode('region', attrs={'position': (0, 2, -6), 'scale': (
|
self.mapFGP6col = bs.newnode('region', attrs={'position': (1.5, 2, -6), 'scale': (
|
||||||
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
||||||
self.coldel6 = False
|
self.coldel6 = False
|
||||||
|
|
||||||
if self.coldel7:
|
if self.coldel7:
|
||||||
self.mapFGP7 = ba.newnode('prop',
|
self.mapFGP7 = bs.newnode('prop',
|
||||||
attrs={'body': 'puck', 'position': (0, 2, -3), 'model': self._mapFGPModel, 'model_scale': 3.8, 'body_scale': 3.8, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
attrs={'body': 'puck', 'position': (1.5, 2, -3), 'mesh': self._mapFGPModel, 'mesh_scale': 3.73, 'body_scale': 3.73, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
||||||
self.mapFGP7Tex = None
|
self.mapFGP7Tex = None
|
||||||
self.mapFGP7col = ba.newnode('region', attrs={'position': (0, 2, -3), 'scale': (
|
self.mapFGP7col = bs.newnode('region', attrs={'position': (1.5, 2, -3), 'scale': (
|
||||||
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
||||||
self.coldel7 = False
|
self.coldel7 = False
|
||||||
|
|
||||||
if self.coldel8:
|
if self.coldel8:
|
||||||
self.mapFGP8 = ba.newnode('prop',
|
self.mapFGP8 = bs.newnode('prop',
|
||||||
attrs={'body': 'puck', 'position': (0, 2, 0), 'model': self._mapFGPModel, 'model_scale': 3.8, 'body_scale': 3.8, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
attrs={'body': 'puck', 'position': (1.5, 2, 0), 'mesh': self._mapFGPModel, 'mesh_scale': 3.73, 'body_scale': 3.73, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
||||||
self.mapFGP8Tex = None
|
self.mapFGP8Tex = None
|
||||||
self.mapFGP8col = ba.newnode('region', attrs={'position': (0, 2, 0), 'scale': (
|
self.mapFGP8col = bs.newnode('region', attrs={'position': (1.5, 2, 0), 'scale': (
|
||||||
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
||||||
self.coldel8 = False
|
self.coldel8 = False
|
||||||
|
|
||||||
if self.coldel9:
|
if self.coldel9:
|
||||||
self.mapFGP9 = ba.newnode('prop',
|
self.mapFGP9 = bs.newnode('prop',
|
||||||
attrs={'body': 'puck', 'position': (-3, 2, -9), 'model': self._mapFGPModel, 'model_scale': 3.8, 'body_scale': 3.8, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
attrs={'body': 'puck', 'position': (-1.5, 2, -9), 'mesh': self._mapFGPModel, 'mesh_scale': 3.73, 'body_scale': 3.73, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
||||||
self.mapFGP9Tex = None
|
self.mapFGP9Tex = None
|
||||||
self.mapFGP9col = ba.newnode('region', attrs={'position': (-3, 2, -9), 'scale': (
|
self.mapFGP9col = bs.newnode('region', attrs={'position': (-1.5, 2, -9), 'scale': (
|
||||||
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
||||||
self.coldel9 = False
|
self.coldel9 = False
|
||||||
|
|
||||||
if self.coldel10:
|
if self.coldel10:
|
||||||
self.mapFGP10 = ba.newnode('prop',
|
self.mapFGP10 = bs.newnode('prop',
|
||||||
attrs={'body': 'puck', 'position': (-3, 2, -6), 'model': self._mapFGPModel, 'model_scale': 3.8, 'body_scale': 3.8, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
attrs={'body': 'puck', 'position': (-1.5, 2, -6), 'mesh': self._mapFGPModel, 'mesh_scale': 3.73, 'body_scale': 3.73, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
||||||
self.mapFGP10Tex = None
|
self.mapFGP10Tex = None
|
||||||
self.mapFGP10col = ba.newnode('region', attrs={'position': (-3, 2, -6), 'scale': (
|
self.mapFGP10col = bs.newnode('region', attrs={'position': (-1.5, 2, -6), 'scale': (
|
||||||
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
||||||
self.coldel10 = False
|
self.coldel10 = False
|
||||||
|
|
||||||
if self.coldel11:
|
if self.coldel11:
|
||||||
self.mapFGP11 = ba.newnode('prop',
|
self.mapFGP11 = bs.newnode('prop',
|
||||||
attrs={'body': 'puck', 'position': (-3, 2, -3), 'model': self._mapFGPModel, 'model_scale': 3.8, 'body_scale': 3.8, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
attrs={'body': 'puck', 'position': (-1.5, 2, -3), 'mesh': self._mapFGPModel, 'mesh_scale': 3.73, 'body_scale': 3.73, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
||||||
self.mapFGP11Tex = None
|
self.mapFGP11Tex = None
|
||||||
self.mapFGP11col = ba.newnode('region', attrs={'position': (-3, 2, -3), 'scale': (
|
self.mapFGP11col = bs.newnode('region', attrs={'position': (-1.5, 2, -3), 'scale': (
|
||||||
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
||||||
self.coldel11 = False
|
self.coldel11 = False
|
||||||
|
|
||||||
if self.coldel12:
|
if self.coldel12:
|
||||||
self.mapFGP12 = ba.newnode('prop',
|
self.mapFGP12 = bs.newnode('prop',
|
||||||
attrs={'body': 'puck', 'position': (-3, 2, 0), 'model': self._mapFGPModel, 'model_scale': 3.8, 'body_scale': 3.8, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
attrs={'body': 'puck', 'position': (-1.5, 2, 0), 'mesh': self._mapFGPModel, 'mesh_scale': 3.73, 'body_scale': 3.73, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
||||||
self.mapFGP12Tex = None
|
self.mapFGP12Tex = None
|
||||||
self.mapFGP12col = ba.newnode('region', attrs={'position': (-3, 2, 0), 'scale': (
|
self.mapFGP12col = bs.newnode('region', attrs={'position': (-1.5, 2, 0), 'scale': (
|
||||||
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
||||||
self.coldel12 = False
|
self.coldel12 = False
|
||||||
|
|
||||||
if self.coldel13:
|
if self.coldel13:
|
||||||
self.mapFGP13 = ba.newnode('prop',
|
self.mapFGP13 = bs.newnode('prop',
|
||||||
attrs={'body': 'puck', 'position': (-6, 2, -9), 'model': self._mapFGPModel, 'model_scale': 3.8, 'body_scale': 3.8, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
attrs={'body': 'puck', 'position': (-4.5, 2, -9), 'mesh': self._mapFGPModel, 'mesh_scale': 3.73, 'body_scale': 3.73, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
||||||
self.mapFGP13Tex = None
|
self.mapFGP13Tex = None
|
||||||
self.mapFGP13col = ba.newnode('region', attrs={'position': (-6, 2, -9), 'scale': (
|
self.mapFGP13col = bs.newnode('region', attrs={'position': (-4.5, 2, -9), 'scale': (
|
||||||
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
||||||
self.coldel13 = False
|
self.coldel13 = False
|
||||||
|
|
||||||
if self.coldel14:
|
if self.coldel14:
|
||||||
self.mapFGP14 = ba.newnode('prop',
|
self.mapFGP14 = bs.newnode('prop',
|
||||||
attrs={'body': 'puck', 'position': (-6, 2, -6), 'model': self._mapFGPModel, 'model_scale': 3.8, 'body_scale': 3.8, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
attrs={'body': 'puck', 'position': (-4.5, 2, -6), 'mesh': self._mapFGPModel, 'mesh_scale': 3.73, 'body_scale': 3.73, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
||||||
self.mapFGP14Tex = None
|
self.mapFGP14Tex = None
|
||||||
self.mapFGP14col = ba.newnode('region', attrs={'position': (-6, 2, -6), 'scale': (
|
self.mapFGP14col = bs.newnode('region', attrs={'position': (-4.5, 2, -6), 'scale': (
|
||||||
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
||||||
self.coldel14 = False
|
self.coldel14 = False
|
||||||
|
|
||||||
if self.coldel15:
|
if self.coldel15:
|
||||||
self.mapFGP15 = ba.newnode('prop',
|
self.mapFGP15 = bs.newnode('prop',
|
||||||
attrs={'body': 'puck', 'position': (-6, 2, -3), 'model': self._mapFGPModel, 'model_scale': 3.8, 'body_scale': 3.8, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
attrs={'body': 'puck', 'position': (-4.5, 2, -3), 'mesh': self._mapFGPModel, 'mesh_scale': 3.73, 'body_scale': 3.73, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
||||||
self.mapFGP15Tex = None
|
self.mapFGP15Tex = None
|
||||||
self.mapFGP15col = ba.newnode('region', attrs={'position': (-6, 2, -3), 'scale': (
|
self.mapFGP15col = bs.newnode('region', attrs={'position': (-4.5, 2, -3), 'scale': (
|
||||||
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
||||||
self.coldel15 = False
|
self.coldel15 = False
|
||||||
|
|
||||||
if self.coldel16:
|
if self.coldel16:
|
||||||
self.mapFGP16 = ba.newnode('prop',
|
self.mapFGP16 = bs.newnode('prop',
|
||||||
attrs={'body': 'puck', 'position': (-6, 2, 0), 'model': self._mapFGPModel, 'model_scale': 3.8, 'body_scale': 3.8, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
attrs={'body': 'puck', 'position': (-4.5, 2, 0), 'mesh': self._mapFGPModel, 'mesh_scale': 3.73, 'body_scale': 3.73, 'shadow_size': 0.5, 'gravity_scale': 0.0, 'color_texture': self._mapFGPDefaultTex, 'reflection': 'soft', 'reflection_scale': [1.0], 'is_area_of_interest': True, 'materials': [self.dont_collide]})
|
||||||
self.mapFGP16Tex = None
|
self.mapFGP16Tex = None
|
||||||
self.mapFGP16col = ba.newnode('region', attrs={'position': (-6, 2, 0), 'scale': (
|
self.mapFGP16col = bs.newnode('region', attrs={'position': (-4.5, 2, 0), 'scale': (
|
||||||
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
3.5, 0.1, 3.5), 'type': 'box', 'materials': (self._collide_with_player, shared.footing_material)})
|
||||||
self.coldel16 = False
|
self.coldel16 = False
|
||||||
|
|
||||||
|
|
@ -843,27 +829,27 @@ class MGgame(ba.TeamGameActivity[Player, Team]):
|
||||||
timeStart = 6
|
timeStart = 6
|
||||||
else:
|
else:
|
||||||
timeStart = 2
|
timeStart = 2
|
||||||
ba.playsound(self._scoreSound)
|
self._scoreSound.play()
|
||||||
activity = _ba.get_foreground_host_activity()
|
activity = bs.get_foreground_host_activity()
|
||||||
for i in activity.players:
|
for i in activity.players:
|
||||||
try:
|
try:
|
||||||
i.actor.node.handlemessage(ba.CelebrateMessage(2.0))
|
i.actor.node.handlemessage(bs.CelebrateMessage(2.0))
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
ba.timer(timeStart, self._randomPlatform)
|
bs.timer(timeStart, self._randomPlatform)
|
||||||
ba.timer(timeStart, self.startCounter)
|
bs.timer(timeStart, self.startCounter)
|
||||||
|
|
||||||
self.spawnAllMap()
|
self.spawnAllMap()
|
||||||
self.flashHide()
|
self.flashHide()
|
||||||
|
|
||||||
# Various high-level game events come through this method.
|
# Various high-level game events come through this method.
|
||||||
def handlemessage(self, msg: Any) -> Any:
|
def handlemessage(self, msg: Any) -> Any:
|
||||||
if isinstance(msg, ba.PlayerDiedMessage):
|
if isinstance(msg, bs.PlayerDiedMessage):
|
||||||
|
|
||||||
# Augment standard behavior.
|
# Augment standard behavior.
|
||||||
super().handlemessage(msg)
|
super().handlemessage(msg)
|
||||||
|
|
||||||
curtime = ba.time()
|
curtime = bs.time()
|
||||||
|
|
||||||
# Record the player's moment of death.
|
# Record the player's moment of death.
|
||||||
# assert isinstance(msg.spaz.player
|
# assert isinstance(msg.spaz.player
|
||||||
|
|
@ -873,15 +859,15 @@ class MGgame(ba.TeamGameActivity[Player, Team]):
|
||||||
# (more accurate looking).
|
# (more accurate looking).
|
||||||
# In teams/ffa, allow a one-second fudge-factor so we can
|
# In teams/ffa, allow a one-second fudge-factor so we can
|
||||||
# get more draws if players die basically at the same time.
|
# get more draws if players die basically at the same time.
|
||||||
if isinstance(self.session, ba.CoopSession):
|
if isinstance(self.session, bs.CoopSession):
|
||||||
# Teams will still show up if we check now.. check in
|
# Teams will still show up if we check now.. check in
|
||||||
# the next cycle.
|
# the next cycle.
|
||||||
ba.pushcall(self._check_end_game)
|
babase.pushcall(self._check_end_game)
|
||||||
|
|
||||||
# Also record this for a final setting of the clock.
|
# Also record this for a final setting of the clock.
|
||||||
self._last_player_death_time = curtime
|
self._last_player_death_time = curtime
|
||||||
else:
|
else:
|
||||||
ba.timer(1.0, self._check_end_game)
|
bs.timer(1.0, self._check_end_game)
|
||||||
else:
|
else:
|
||||||
# Default handler:
|
# Default handler:
|
||||||
return super().handlemessage(msg)
|
return super().handlemessage(msg)
|
||||||
|
|
@ -897,7 +883,7 @@ class MGgame(ba.TeamGameActivity[Player, Team]):
|
||||||
|
|
||||||
# In co-op, we go till everyone is dead.. otherwise we go
|
# In co-op, we go till everyone is dead.. otherwise we go
|
||||||
# until one team remains.
|
# until one team remains.
|
||||||
if isinstance(self.session, ba.CoopSession):
|
if isinstance(self.session, bs.CoopSession):
|
||||||
if living_team_count <= 0:
|
if living_team_count <= 0:
|
||||||
self.end_game()
|
self.end_game()
|
||||||
else:
|
else:
|
||||||
|
|
@ -905,7 +891,7 @@ class MGgame(ba.TeamGameActivity[Player, Team]):
|
||||||
self.end_game()
|
self.end_game()
|
||||||
|
|
||||||
def end_game(self) -> None:
|
def end_game(self) -> None:
|
||||||
cur_time = ba.time()
|
cur_time = bs.time()
|
||||||
assert self._timer is not None
|
assert self._timer is not None
|
||||||
start_time = self._timer.getstarttime()
|
start_time = self._timer.getstarttime()
|
||||||
|
|
||||||
|
|
@ -936,7 +922,7 @@ class MGgame(ba.TeamGameActivity[Player, Team]):
|
||||||
|
|
||||||
# Ok now calc game results: set a score for each team and then tell
|
# Ok now calc game results: set a score for each team and then tell
|
||||||
# the game to end.
|
# the game to end.
|
||||||
results = ba.GameResults()
|
results = bs.GameResults()
|
||||||
|
|
||||||
# Remember that 'free-for-all' mode is simply a special form
|
# Remember that 'free-for-all' mode is simply a special form
|
||||||
# of 'teams' mode where each player gets their own team, so we can
|
# of 'teams' mode where each player gets their own team, so we can
|
||||||
|
|
@ -965,7 +951,7 @@ class MGdefs():
|
||||||
(0.0, 0.0, 0.0) + (29.23565494, 14.19991443, 29.92689344)
|
(0.0, 0.0, 0.0) + (29.23565494, 14.19991443, 29.92689344)
|
||||||
|
|
||||||
|
|
||||||
class MGmap(ba.Map):
|
class MGmap(bs.Map):
|
||||||
defs = MGdefs()
|
defs = MGdefs()
|
||||||
name = 'Sky Tiles'
|
name = 'Sky Tiles'
|
||||||
|
|
||||||
|
|
@ -981,23 +967,23 @@ class MGmap(ba.Map):
|
||||||
@classmethod
|
@classmethod
|
||||||
def on_preload(cls) -> Any:
|
def on_preload(cls) -> Any:
|
||||||
data: Dict[str, Any] = {
|
data: Dict[str, Any] = {
|
||||||
'bgtex': ba.gettexture('menuBG'),
|
'bgtex': bs.gettexture('menuBG'),
|
||||||
'bgmodel': ba.getmodel('thePadBG')
|
'bgmesh': bs.getmesh('thePadBG')
|
||||||
}
|
}
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
shared = SharedObjects.get()
|
shared = SharedObjects.get()
|
||||||
self.node = ba.newnode(
|
self.node = bs.newnode(
|
||||||
'terrain',
|
'terrain',
|
||||||
attrs={
|
attrs={
|
||||||
'model': self.preloaddata['bgmodel'],
|
'mesh': self.preloaddata['bgmesh'],
|
||||||
'lighting': False,
|
'lighting': False,
|
||||||
'background': True,
|
'background': True,
|
||||||
'color_texture': self.preloaddata['bgtex']
|
'color_texture': self.preloaddata['bgtex']
|
||||||
})
|
})
|
||||||
gnode = ba.getactivity().globalsnode
|
gnode = bs.getactivity().globalsnode
|
||||||
gnode.tint = (1.3, 1.2, 1.0)
|
gnode.tint = (1.3, 1.2, 1.0)
|
||||||
gnode.ambient_color = (1.3, 1.2, 1.0)
|
gnode.ambient_color = (1.3, 1.2, 1.0)
|
||||||
gnode.vignette_outer = (0.57, 0.57, 0.57)
|
gnode.vignette_outer = (0.57, 0.57, 0.57)
|
||||||
|
|
@ -1006,12 +992,12 @@ class MGmap(ba.Map):
|
||||||
gnode.vr_near_clip = 0.5
|
gnode.vr_near_clip = 0.5
|
||||||
|
|
||||||
|
|
||||||
ba._map.register_map(MGmap)
|
bs._map.register_map(MGmap)
|
||||||
|
|
||||||
|
|
||||||
# ba_meta export plugin
|
# ba_meta export plugin
|
||||||
class byFreaku(ba.Plugin):
|
class byFreaku(babase.Plugin):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
## Campaign support ##
|
## Campaign support ##
|
||||||
ba.app.add_coop_practice_level(ba.Level(name='Memory Game', displayname='${GAME}', gametype=MGgame, settings={
|
babase.app.classic.add_coop_practice_level(bs.Level(
|
||||||
}, preview_texture_name='achievementOffYouGo'))
|
name='Memory Game', displayname='${GAME}', gametype=MGgame, settings={}, preview_texture_name='achievementOffYouGo'))
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# Made by MattZ45986 on GitHub
|
# Made by MattZ45986 on GitHub
|
||||||
# Ported by: Freaku / @[Just] Freak#4999
|
# Ported by your friend: Freaku
|
||||||
|
|
||||||
|
|
||||||
# Bug Fixes & Improvements as well...
|
# Bug Fixes & Improvements as well...
|
||||||
|
|
@ -10,76 +10,69 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
import _ba
|
import _babase
|
||||||
import ba
|
|
||||||
import random
|
import random
|
||||||
import math
|
import math
|
||||||
from bastd.actor.flag import Flag, FlagPickedUpMessage
|
import bascenev1 as bs
|
||||||
from bastd.actor.playerspaz import PlayerSpaz
|
from bascenev1lib.actor.flag import Flag, FlagPickedUpMessage
|
||||||
|
from bascenev1lib.actor.playerspaz import PlayerSpaz
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any, Type, List, Dict, Tuple, Union, Sequence, Optional
|
from typing import Any, Type, List, Dict, Tuple, Union, Sequence, Optional
|
||||||
|
|
||||||
|
|
||||||
class Player(ba.Player['Team']):
|
class Player(bs.Player['Team']):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.done: bool = False
|
self.done: bool = False
|
||||||
self.survived: bool = True
|
self.survived: bool = True
|
||||||
|
|
||||||
|
|
||||||
class Team(ba.Team[Player]):
|
class Team(bs.Team[Player]):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.score = 0
|
self.score = 0
|
||||||
|
|
||||||
|
|
||||||
# ba_meta require api 7
|
# ba_meta require api 8
|
||||||
# ba_meta export game
|
# ba_meta export bascenev1.GameActivity
|
||||||
class MFGame(ba.TeamGameActivity[Player, Team]):
|
class MFGame(bs.TeamGameActivity[Player, Team]):
|
||||||
name = 'Musical Flags'
|
name = 'Musical Flags'
|
||||||
description = "Don't be the one stuck without a flag!"
|
description = "Don't be the one stuck without a flag!"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_available_settings(
|
def get_available_settings(
|
||||||
cls, sessiontype: Type[ba.Session]) -> List[ba.Setting]:
|
cls, sessiontype: Type[bs.Session]) -> List[babase.Setting]:
|
||||||
settings = [
|
settings = [
|
||||||
ba.IntChoiceSetting(
|
bs.IntSetting(
|
||||||
'Time Limit',
|
'Max Round Time',
|
||||||
choices=[
|
min_value=15,
|
||||||
('None', 0),
|
default=25,
|
||||||
('1 Minute', 60),
|
increment=5,
|
||||||
('2 Minutes', 120),
|
|
||||||
('5 Minutes', 300),
|
|
||||||
('10 Minutes', 600),
|
|
||||||
('20 Minutes', 1200),
|
|
||||||
],
|
|
||||||
default=0,
|
|
||||||
),
|
),
|
||||||
ba.BoolSetting('Epic Mode', default=False),
|
bs.BoolSetting('Epic Mode', default=False),
|
||||||
ba.BoolSetting('Enable Running', default=True),
|
bs.BoolSetting('Enable Running', default=True),
|
||||||
ba.BoolSetting('Enable Punching', default=False),
|
bs.BoolSetting('Enable Punching', default=False),
|
||||||
ba.BoolSetting('Enable Bottom Credit', True)
|
bs.BoolSetting('Enable Bottom Credit', True)
|
||||||
]
|
]
|
||||||
return settings
|
return settings
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
|
def supports_session_type(cls, sessiontype: Type[bs.Session]) -> bool:
|
||||||
return (issubclass(sessiontype, ba.DualTeamSession)
|
return (issubclass(sessiontype, bs.DualTeamSession)
|
||||||
or issubclass(sessiontype, ba.FreeForAllSession))
|
or issubclass(sessiontype, bs.FreeForAllSession))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
|
def get_supported_maps(cls, sessiontype: Type[bs.Session]) -> List[str]:
|
||||||
return ['Doom Shroom']
|
return ['Doom Shroom']
|
||||||
|
|
||||||
def __init__(self, settings: dict):
|
def __init__(self, settings: dict):
|
||||||
super().__init__(settings)
|
super().__init__(settings)
|
||||||
self.nodes = []
|
self.nodes = []
|
||||||
self._dingsound = ba.getsound('dingSmall')
|
self._dingsound = bs.getsound('dingSmall')
|
||||||
self._epic_mode = bool(settings['Epic Mode'])
|
self._epic_mode = bool(settings['Epic Mode'])
|
||||||
self.credit_text = bool(settings['Enable Bottom Credit'])
|
self.credit_text = bool(settings['Enable Bottom Credit'])
|
||||||
self._time_limit = float(settings['Time Limit'])
|
|
||||||
self.is_punch = bool(settings['Enable Punching'])
|
self.is_punch = bool(settings['Enable Punching'])
|
||||||
self.is_run = bool(settings['Enable Running'])
|
self.is_run = bool(settings['Enable Running'])
|
||||||
|
|
||||||
self._textRound = ba.newnode('text',
|
self._textRound = bs.newnode('text',
|
||||||
attrs={'text': '',
|
attrs={'text': '',
|
||||||
'position': (0, -38),
|
'position': (0, -38),
|
||||||
'scale': 1,
|
'scale': 1,
|
||||||
|
|
@ -91,10 +84,16 @@ class MFGame(ba.TeamGameActivity[Player, Team]):
|
||||||
'h_attach': 'center',
|
'h_attach': 'center',
|
||||||
'h_align': 'center',
|
'h_align': 'center',
|
||||||
'v_align': 'center'})
|
'v_align': 'center'})
|
||||||
|
self.round_time = int(settings['Max Round Time'])
|
||||||
|
self.reset_round_time = int(settings['Max Round Time'])
|
||||||
|
self.should_die_occur = True
|
||||||
|
self.round_time_textnode = bs.newnode('text',
|
||||||
|
attrs={
|
||||||
|
'text': "", 'flatness': 1.0, 'h_align': 'center', 'h_attach': 'center', 'v_attach': 'top', 'v_align': 'center', 'position': (0, -15), 'scale': 0.9, 'color': (1, 0.7, 0.9)})
|
||||||
|
|
||||||
self.slow_motion = self._epic_mode
|
self.slow_motion = self._epic_mode
|
||||||
# A cool music, matching our gamemode theme
|
# A cool music, matching our gamemode theme
|
||||||
self.default_music = ba.MusicType.FLAG_CATCHER
|
self.default_music = bs.MusicType.FLAG_CATCHER
|
||||||
|
|
||||||
def get_instance_description(self) -> Union[str, Sequence]:
|
def get_instance_description(self) -> Union[str, Sequence]:
|
||||||
return 'Catch Flag for yourself'
|
return 'Catch Flag for yourself'
|
||||||
|
|
@ -104,8 +103,8 @@ class MFGame(ba.TeamGameActivity[Player, Team]):
|
||||||
|
|
||||||
def on_player_join(self, player: Player) -> None:
|
def on_player_join(self, player: Player) -> None:
|
||||||
if self.has_begun():
|
if self.has_begun():
|
||||||
ba.screenmessage(
|
bs.broadcastmessage(
|
||||||
ba.Lstr(resource='playerDelayedJoinText',
|
bs.Lstr(resource='playerDelayedJoinText',
|
||||||
subs=[('${PLAYER}', player.getname(full=True))]),
|
subs=[('${PLAYER}', player.getname(full=True))]),
|
||||||
color=(0, 1, 0), transient=True)
|
color=(0, 1, 0), transient=True)
|
||||||
player.survived = False
|
player.survived = False
|
||||||
|
|
@ -115,7 +114,7 @@ class MFGame(ba.TeamGameActivity[Player, Team]):
|
||||||
def on_player_leave(self, player: Player) -> None:
|
def on_player_leave(self, player: Player) -> None:
|
||||||
super().on_player_leave(player)
|
super().on_player_leave(player)
|
||||||
# A departing player may trigger game-over.
|
# A departing player may trigger game-over.
|
||||||
self.checkEnd()
|
bs.timer(0, self.checkEnd)
|
||||||
|
|
||||||
def on_begin(self) -> None:
|
def on_begin(self) -> None:
|
||||||
super().on_begin()
|
super().on_begin()
|
||||||
|
|
@ -124,9 +123,8 @@ class MFGame(ba.TeamGameActivity[Player, Team]):
|
||||||
self.nodes = []
|
self.nodes = []
|
||||||
self.flags = []
|
self.flags = []
|
||||||
self.spawned = []
|
self.spawned = []
|
||||||
self.setup_standard_time_limit(self._time_limit)
|
|
||||||
if self.credit_text:
|
if self.credit_text:
|
||||||
t = ba.newnode('text',
|
t = bs.newnode('text',
|
||||||
attrs={'text': "Ported by Freaku\nMade by MattZ45986", # Disable 'Enable Bottom Credits' when making playlist, No need to edit this lovely...
|
attrs={'text': "Ported by Freaku\nMade by MattZ45986", # Disable 'Enable Bottom Credits' when making playlist, No need to edit this lovely...
|
||||||
'scale': 0.7,
|
'scale': 0.7,
|
||||||
'position': (0, 0),
|
'position': (0, 0),
|
||||||
|
|
@ -137,7 +135,32 @@ class MFGame(ba.TeamGameActivity[Player, Team]):
|
||||||
'v_attach': 'bottom'})
|
'v_attach': 'bottom'})
|
||||||
self.makeRound()
|
self.makeRound()
|
||||||
self._textRound.text = 'Round ' + str(self.roundNum)
|
self._textRound.text = 'Round ' + str(self.roundNum)
|
||||||
ba.timer(5, self.checkEnd)
|
bs.timer(3, self.checkEnd)
|
||||||
|
self.keepcalling = bs.timer(1, self._timeround, True)
|
||||||
|
|
||||||
|
def _timeround(self):
|
||||||
|
if self.round_time == 0 and self.should_die_occur:
|
||||||
|
self.should_die_occur = False
|
||||||
|
self.round_time_textnode.opacity = 0
|
||||||
|
bs.broadcastmessage('Proceeding Round...')
|
||||||
|
for player in self.spawned:
|
||||||
|
if not player.done:
|
||||||
|
try:
|
||||||
|
player.survived = False
|
||||||
|
player.actor.handlemessage(bs.StandMessage((0, 3, -2)))
|
||||||
|
bs.timer(0.5, bs.Call(player.actor.handlemessage, bs.FreezeMessage()))
|
||||||
|
bs.timer(1.5, bs.Call(player.actor.handlemessage, bs.FreezeMessage()))
|
||||||
|
bs.timer(2.5, bs.Call(player.actor.handlemessage, bs.FreezeMessage()))
|
||||||
|
bs.timer(3, bs.Call(player.actor.handlemessage, bs.ShouldShatterMessage()))
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
bs.timer(3.5, self.killRound)
|
||||||
|
bs.timer(3.55, self.makeRound)
|
||||||
|
self.round_time_textnode.opacity = 0
|
||||||
|
self.round_time = self.reset_round_time
|
||||||
|
else:
|
||||||
|
self.round_time_textnode.text = "Time: " + str(self.round_time)
|
||||||
|
self.round_time -= 1
|
||||||
|
|
||||||
def makeRound(self):
|
def makeRound(self):
|
||||||
for player in self.players:
|
for player in self.players:
|
||||||
|
|
@ -147,6 +170,9 @@ class MFGame(ba.TeamGameActivity[Player, Team]):
|
||||||
self._textRound.text = 'Round ' + str(self.roundNum)
|
self._textRound.text = 'Round ' + str(self.roundNum)
|
||||||
self.flags = []
|
self.flags = []
|
||||||
self.spawned = []
|
self.spawned = []
|
||||||
|
self.should_die_occur = True
|
||||||
|
self.round_time = self.reset_round_time
|
||||||
|
self.round_time_textnode.opacity = 1
|
||||||
angle = random.randint(0, 359)
|
angle = random.randint(0, 359)
|
||||||
c = 0
|
c = 0
|
||||||
for player in self.players:
|
for player in self.players:
|
||||||
|
|
@ -165,6 +191,13 @@ class MFGame(ba.TeamGameActivity[Player, Team]):
|
||||||
self.checkEnd()
|
self.checkEnd()
|
||||||
colors = [(1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 1, 0), (1, 0, 1), (0, 1, 1), (0, 0, 0),
|
colors = [(1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 1, 0), (1, 0, 1), (0, 1, 1), (0, 0, 0),
|
||||||
(0.5, 0.8, 0), (0, 0.8, 0.5), (0.8, 0.25, 0.7), (0, 0.27, 0.55), (2, 2, 0.6), (0.4, 3, 0.85)]
|
(0.5, 0.8, 0), (0, 0.8, 0.5), (0.8, 0.25, 0.7), (0, 0.27, 0.55), (2, 2, 0.6), (0.4, 3, 0.85)]
|
||||||
|
|
||||||
|
# Add support for more than 13 players
|
||||||
|
if c > 12:
|
||||||
|
for i in range(c-12):
|
||||||
|
colors.append((random.uniform(0.1, 1), random.uniform(
|
||||||
|
0.1, 1), random.uniform(0.1, 1)))
|
||||||
|
|
||||||
# Smart Mathematics:
|
# Smart Mathematics:
|
||||||
# All Flags spawn same distance from the players
|
# All Flags spawn same distance from the players
|
||||||
for i in range(c-1):
|
for i in range(c-1):
|
||||||
|
|
@ -179,19 +212,19 @@ class MFGame(ba.TeamGameActivity[Player, Team]):
|
||||||
self.numPickedUp = 0
|
self.numPickedUp = 0
|
||||||
for player in self.players:
|
for player in self.players:
|
||||||
if player.is_alive():
|
if player.is_alive():
|
||||||
player.actor.handlemessage(ba.DieMessage())
|
player.actor.handlemessage(bs.DieMessage())
|
||||||
for flag in self.flags:
|
for flag in self.flags:
|
||||||
flag.node.delete()
|
flag.node.delete()
|
||||||
for light in self.nodes:
|
for light in self.nodes:
|
||||||
light.delete()
|
light.delete()
|
||||||
|
|
||||||
def spawn_player(self, player: Player, pos: tuple = (0, 0, 0)) -> ba.Actor:
|
def spawn_player(self, player: Player, pos: tuple = (0, 0, 0)) -> bs.Actor:
|
||||||
spaz = self.spawn_player_spaz(player)
|
spaz = self.spawn_player_spaz(player)
|
||||||
if pos == (0, 0, 0):
|
if pos == (0, 0, 0):
|
||||||
pos = (-.5+random.random()*2, 3+random.random()*2, -5+random.random()*2)
|
pos = (-.5+random.random()*2, 3+random.random()*2, -5+random.random()*2)
|
||||||
spaz.connect_controls_to_player(enable_punch=self.is_punch,
|
spaz.connect_controls_to_player(enable_punch=self.is_punch,
|
||||||
enable_bomb=False, enable_run=self.is_run)
|
enable_bomb=False, enable_run=self.is_run)
|
||||||
spaz.handlemessage(ba.StandMessage(pos))
|
spaz.handlemessage(bs.StandMessage(pos))
|
||||||
return spaz
|
return spaz
|
||||||
|
|
||||||
def check_respawn(self, player):
|
def check_respawn(self, player):
|
||||||
|
|
@ -200,36 +233,38 @@ class MFGame(ba.TeamGameActivity[Player, Team]):
|
||||||
|
|
||||||
def handlemessage(self, msg: Any) -> Any:
|
def handlemessage(self, msg: Any) -> Any:
|
||||||
|
|
||||||
if isinstance(msg, ba.PlayerDiedMessage):
|
if isinstance(msg, bs.PlayerDiedMessage):
|
||||||
super().handlemessage(msg)
|
super().handlemessage(msg)
|
||||||
player = msg.getplayer(Player)
|
player = msg.getplayer(Player)
|
||||||
ba.timer(0.1, ba.Call(self.check_respawn, player))
|
bs.timer(0.1, bs.Call(self.check_respawn, player))
|
||||||
ba.timer(0.5, self.checkEnd)
|
bs.timer(0.5, self.checkEnd)
|
||||||
elif isinstance(msg, FlagPickedUpMessage):
|
elif isinstance(msg, FlagPickedUpMessage):
|
||||||
self.numPickedUp += 1
|
self.numPickedUp += 1
|
||||||
msg.node.getdelegate(PlayerSpaz, True).getplayer(Player, True).done = True
|
msg.node.getdelegate(PlayerSpaz, True).getplayer(Player, True).done = True
|
||||||
l = ba.newnode('light',
|
l = bs.newnode('light',
|
||||||
owner=None,
|
owner=None,
|
||||||
attrs={'color': msg.node.color,
|
attrs={'color': msg.node.color,
|
||||||
'position': (msg.node.position_center),
|
'position': (msg.node.position_center),
|
||||||
'intensity': 1})
|
'intensity': 1})
|
||||||
self.nodes.append(l)
|
self.nodes.append(l)
|
||||||
msg.flag.handlemessage(ba.DieMessage())
|
msg.flag.handlemessage(bs.DieMessage())
|
||||||
msg.node.handlemessage(ba.DieMessage())
|
msg.node.handlemessage(bs.DieMessage())
|
||||||
msg.node.delete()
|
msg.node.delete()
|
||||||
if self.numPickedUp == len(self.flags):
|
if self.numPickedUp == len(self.flags):
|
||||||
|
self.round_time_textnode.opacity = 0
|
||||||
|
self.round_time = self.reset_round_time
|
||||||
for player in self.spawned:
|
for player in self.spawned:
|
||||||
if not player.done:
|
if not player.done:
|
||||||
try:
|
try:
|
||||||
player.survived = False
|
player.survived = False
|
||||||
ba.screenmessage("No Flag? "+player.getname())
|
bs.broadcastmessage("No Flag? "+player.getname())
|
||||||
player.actor.handlemessage(ba.StandMessage((0, 3, -2)))
|
player.actor.handlemessage(bs.StandMessage((0, 3, -2)))
|
||||||
ba.timer(0.5, ba.Call(player.actor.handlemessage, ba.FreezeMessage()))
|
bs.timer(0.5, bs.Call(player.actor.handlemessage, bs.FreezeMessage()))
|
||||||
ba.timer(3, ba.Call(player.actor.handlemessage, ba.ShouldShatterMessage()))
|
bs.timer(3, bs.Call(player.actor.handlemessage, bs.ShouldShatterMessage()))
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
ba.timer(3.5, self.killRound)
|
bs.timer(3.5, self.killRound)
|
||||||
ba.timer(3.55, self.makeRound)
|
bs.timer(3.55, self.makeRound)
|
||||||
else:
|
else:
|
||||||
return super().handlemessage(msg)
|
return super().handlemessage(msg)
|
||||||
return None
|
return None
|
||||||
|
|
@ -243,10 +278,10 @@ class MFGame(ba.TeamGameActivity[Player, Team]):
|
||||||
for player in self.players:
|
for player in self.players:
|
||||||
if player.survived:
|
if player.survived:
|
||||||
player.team.score += 10
|
player.team.score += 10
|
||||||
ba.timer(2.5, self.end_game)
|
bs.timer(2.5, self.end_game)
|
||||||
|
|
||||||
def end_game(self) -> None:
|
def end_game(self) -> None:
|
||||||
results = ba.GameResults()
|
results = bs.GameResults()
|
||||||
for team in self.teams:
|
for team in self.teams:
|
||||||
results.set_team_score(team, team.score)
|
results.set_team_score(team, team.score)
|
||||||
self.end(results=results)
|
self.end(results=results)
|
||||||
|
|
|
||||||
624
plugins/minigames/quake_original.py
Normal file
624
plugins/minigames/quake_original.py
Normal file
|
|
@ -0,0 +1,624 @@
|
||||||
|
# Created By Idk
|
||||||
|
# Ported to 1.7 by Yan
|
||||||
|
|
||||||
|
# ba_meta require api 8
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from bascenev1lib.actor.powerupbox import PowerupBox as Powerup
|
||||||
|
from bascenev1lib.actor.playerspaz import PlayerSpaz
|
||||||
|
from bascenev1lib.actor.scoreboard import Scoreboard
|
||||||
|
from bascenev1lib.gameutils import SharedObjects
|
||||||
|
|
||||||
|
import bascenev1lib.actor.bomb
|
||||||
|
import bascenev1lib.actor.spaz
|
||||||
|
import weakref
|
||||||
|
import random
|
||||||
|
import math
|
||||||
|
import babase
|
||||||
|
import bauiv1 as bui
|
||||||
|
import bascenev1 as bs
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class TouchedToSpaz(object):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class TouchedToAnything(object):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class TouchedToFootingMaterial(object):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class QuakeBallFactory(object):
|
||||||
|
"""Components used by QuakeBall stuff
|
||||||
|
|
||||||
|
category: Game Classes
|
||||||
|
|
||||||
|
"""
|
||||||
|
_STORENAME = babase.storagename()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get(cls) -> QuakeBallFactory:
|
||||||
|
"""Get/create a shared bascenev1lib.actor.bomb.BombFactory object."""
|
||||||
|
activity = bs.getactivity()
|
||||||
|
factory = activity.customdata.get(cls._STORENAME)
|
||||||
|
if factory is None:
|
||||||
|
factory = QuakeBallFactory()
|
||||||
|
activity.customdata[cls._STORENAME] = factory
|
||||||
|
assert isinstance(factory, QuakeBallFactory)
|
||||||
|
return factory
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
shared = SharedObjects.get()
|
||||||
|
|
||||||
|
self.ball_material = bs.Material()
|
||||||
|
|
||||||
|
self.ball_material.add_actions(
|
||||||
|
conditions=((('we_are_younger_than', 5), 'or', ('they_are_younger_than', 50)),
|
||||||
|
'and', ('they_have_material', shared.object_material)),
|
||||||
|
actions=(('modify_node_collision', 'collide', False)))
|
||||||
|
|
||||||
|
self.ball_material.add_actions(
|
||||||
|
conditions=('they_have_material', shared.pickup_material),
|
||||||
|
actions=(('modify_part_collision', 'use_node_collide', False)))
|
||||||
|
|
||||||
|
self.ball_material.add_actions(
|
||||||
|
actions=('modify_part_collision', 'friction', 0))
|
||||||
|
|
||||||
|
self.ball_material.add_actions(
|
||||||
|
conditions=('they_have_material', shared.player_material),
|
||||||
|
actions=(('modify_part_collision', 'physical', False),
|
||||||
|
('message', 'our_node', 'at_connect', TouchedToSpaz())))
|
||||||
|
|
||||||
|
self.ball_material.add_actions(
|
||||||
|
conditions=(('they_dont_have_material', shared.player_material), 'and',
|
||||||
|
('they_have_material', shared.object_material)),
|
||||||
|
actions=('message', 'our_node', 'at_connect', TouchedToAnything()))
|
||||||
|
|
||||||
|
self.ball_material.add_actions(
|
||||||
|
conditions=(('they_dont_have_material', shared.player_material), 'and',
|
||||||
|
('they_have_material', shared.footing_material)),
|
||||||
|
actions=('message', 'our_node', 'at_connect', TouchedToFootingMaterial()))
|
||||||
|
|
||||||
|
def give(self, spaz):
|
||||||
|
spaz.punch_callback = self.shot
|
||||||
|
self.last_shot = int(bs.time() * 1000)
|
||||||
|
|
||||||
|
def shot(self, spaz):
|
||||||
|
time = int(bs.time() * 1000)
|
||||||
|
if time - self.last_shot > 0.6:
|
||||||
|
self.last_shot = time
|
||||||
|
p1 = spaz.node.position_center
|
||||||
|
p2 = spaz.node.position_forward
|
||||||
|
direction = [p1[0]-p2[0], p2[1]-p1[1], p1[2]-p2[2]]
|
||||||
|
direction[1] = 0.0
|
||||||
|
|
||||||
|
mag = 10.0/babase.Vec3(*direction).length()
|
||||||
|
vel = [v * mag for v in direction]
|
||||||
|
QuakeBall(
|
||||||
|
position=spaz.node.position,
|
||||||
|
velocity=(vel[0]*2, vel[1]*2, vel[2]*2),
|
||||||
|
owner=spaz._player,
|
||||||
|
source_player=spaz._player,
|
||||||
|
color=spaz.node.color).autoretain()
|
||||||
|
|
||||||
|
|
||||||
|
class QuakeBall(bs.Actor):
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
position=(0, 5, 0),
|
||||||
|
velocity=(0, 2, 0),
|
||||||
|
source_player=None,
|
||||||
|
owner=None,
|
||||||
|
color=(random.random(), random.random(), random.random()),
|
||||||
|
light_radius=0
|
||||||
|
):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
shared = SharedObjects.get()
|
||||||
|
b_shared = QuakeBallFactory.get()
|
||||||
|
|
||||||
|
self.source_player = source_player
|
||||||
|
self.owner = owner
|
||||||
|
|
||||||
|
self.node = bs.newnode('prop', delegate=self, attrs={
|
||||||
|
'position': position,
|
||||||
|
'velocity': velocity,
|
||||||
|
'mesh': bs.getmesh('impactBomb'),
|
||||||
|
'body': 'sphere',
|
||||||
|
'color_texture': bs.gettexture('bunnyColor'),
|
||||||
|
'mesh_scale': 0.2,
|
||||||
|
'is_area_of_interest': True,
|
||||||
|
'body_scale': 0.8,
|
||||||
|
'materials': [shared.object_material,
|
||||||
|
b_shared.ball_material]})
|
||||||
|
|
||||||
|
self.light_node = bs.newnode('light', attrs={
|
||||||
|
'position': position,
|
||||||
|
'color': color,
|
||||||
|
'radius': 0.1+light_radius,
|
||||||
|
'volume_intensity_scale': 15.0})
|
||||||
|
|
||||||
|
self.node.connectattr('position', self.light_node, 'position')
|
||||||
|
self.emit_time = bs.Timer(0.015, bs.WeakCall(self.emit), repeat=True)
|
||||||
|
self.life_time = bs.Timer(5.0, bs.WeakCall(self.handlemessage, bs.DieMessage()))
|
||||||
|
|
||||||
|
def emit(self):
|
||||||
|
bs.emitfx(
|
||||||
|
position=self.node.position,
|
||||||
|
velocity=self.node.velocity,
|
||||||
|
count=10,
|
||||||
|
scale=0.4,
|
||||||
|
spread=0.01,
|
||||||
|
chunk_type='spark')
|
||||||
|
|
||||||
|
def handlemessage(self, m):
|
||||||
|
if isinstance(m, TouchedToAnything):
|
||||||
|
node = bs.getcollision().opposingnode
|
||||||
|
if node is not None and node.exists():
|
||||||
|
v = self.node.velocity
|
||||||
|
t = self.node.position
|
||||||
|
hitdir = self.node.velocity
|
||||||
|
m = self.node
|
||||||
|
node.handlemessage(
|
||||||
|
bs.HitMessage(
|
||||||
|
pos=t,
|
||||||
|
velocity=v,
|
||||||
|
magnitude=babase.Vec3(*v).length()*40,
|
||||||
|
velocity_magnitude=babase.Vec3(*v).length()*40,
|
||||||
|
radius=0,
|
||||||
|
srcnode=self.node,
|
||||||
|
source_player=self.source_player,
|
||||||
|
force_direction=hitdir))
|
||||||
|
|
||||||
|
self.node.handlemessage(bs.DieMessage())
|
||||||
|
|
||||||
|
elif isinstance(m, bs.DieMessage):
|
||||||
|
if self.node.exists():
|
||||||
|
velocity = self.node.velocity
|
||||||
|
explosion = bs.newnode('explosion', attrs={
|
||||||
|
'position': self.node.position,
|
||||||
|
'velocity': (velocity[0], max(-1.0, velocity[1]), velocity[2]),
|
||||||
|
'radius': 1,
|
||||||
|
'big': False})
|
||||||
|
|
||||||
|
bs.getsound(random.choice(['impactHard', 'impactHard2', 'impactHard3'])).play(),
|
||||||
|
position = self.node.position
|
||||||
|
|
||||||
|
self.emit_time = None
|
||||||
|
self.light_node.delete()
|
||||||
|
self.node.delete()
|
||||||
|
|
||||||
|
elif isinstance(m, bs.OutOfBoundsMessage):
|
||||||
|
self.handlemessage(bs.DieMessage())
|
||||||
|
|
||||||
|
elif isinstance(m, bs.HitMessage):
|
||||||
|
self.node.handlemessage('impulse', m.pos[0], m.pos[1], m.pos[2],
|
||||||
|
m.velocity[0], m.velocity[1], m.velocity[2],
|
||||||
|
1.0*m.magnitude, 1.0*m.velocity_magnitude, m.radius, 0,
|
||||||
|
m.force_direction[0], m.force_direction[1], m.force_direction[2])
|
||||||
|
|
||||||
|
elif isinstance(m, TouchedToSpaz):
|
||||||
|
node = bs.getcollision() .opposingnode
|
||||||
|
if node is not None and node.exists() and node != self.owner \
|
||||||
|
and node.getdelegate(object)._player.team != self.owner.team:
|
||||||
|
node.handlemessage(bs.FreezeMessage())
|
||||||
|
v = self.node.velocity
|
||||||
|
t = self.node.position
|
||||||
|
hitdir = self.node.velocity
|
||||||
|
|
||||||
|
node.handlemessage(
|
||||||
|
bs.HitMessage(
|
||||||
|
pos=t,
|
||||||
|
velocity=(10, 10, 10),
|
||||||
|
magnitude=50,
|
||||||
|
velocity_magnitude=50,
|
||||||
|
radius=0,
|
||||||
|
srcnode=self.node,
|
||||||
|
source_player=self.source_player,
|
||||||
|
force_direction=hitdir))
|
||||||
|
|
||||||
|
self.node.handlemessage(bs.DieMessage())
|
||||||
|
|
||||||
|
elif isinstance(m, TouchedToFootingMaterial):
|
||||||
|
bs.getsound('blip').play(),
|
||||||
|
position = self.node.position
|
||||||
|
else:
|
||||||
|
super().handlemessage(m)
|
||||||
|
|
||||||
|
|
||||||
|
class Player(bs.Player['Team']):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
class Team(bs.Team[Player]):
|
||||||
|
"""Our team type for this game."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.score = 0
|
||||||
|
|
||||||
|
# ba_meta export bascenev1.GameActivity
|
||||||
|
|
||||||
|
|
||||||
|
class QuakeGame(bs.TeamGameActivity[Player, Team]):
|
||||||
|
"""A game type based on acquiring kills."""
|
||||||
|
|
||||||
|
name = 'Quake'
|
||||||
|
description = 'Kill a set number of enemies to win.'
|
||||||
|
|
||||||
|
# Print messages when players die since it matters here.
|
||||||
|
announce_player_deaths = True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool:
|
||||||
|
return issubclass(sessiontype, bs.DualTeamSession) or issubclass(
|
||||||
|
sessiontype, bs.FreeForAllSession
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]:
|
||||||
|
return ['Doom Shroom', 'Monkey Face', 'Football Stadium']
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_available_settings(
|
||||||
|
cls, sessiontype: type[bs.Session]
|
||||||
|
) -> list[babase.Setting]:
|
||||||
|
settings = [
|
||||||
|
bs.IntSetting(
|
||||||
|
'Kills to Win Per Player',
|
||||||
|
min_value=1,
|
||||||
|
default=5,
|
||||||
|
increment=1,
|
||||||
|
),
|
||||||
|
bs.IntChoiceSetting(
|
||||||
|
'Time Limit',
|
||||||
|
choices=[
|
||||||
|
('None', 0),
|
||||||
|
('1 Minute', 60),
|
||||||
|
('2 Minutes', 120),
|
||||||
|
('5 Minutes', 300),
|
||||||
|
('10 Minutes', 600),
|
||||||
|
('20 Minutes', 1200),
|
||||||
|
],
|
||||||
|
default=0,
|
||||||
|
),
|
||||||
|
bs.FloatChoiceSetting(
|
||||||
|
'Respawn Times',
|
||||||
|
choices=[
|
||||||
|
('Shorter', 0.25),
|
||||||
|
('Short', 0.5),
|
||||||
|
('Normal', 1.0),
|
||||||
|
('Long', 2.0),
|
||||||
|
('Longer', 4.0),
|
||||||
|
],
|
||||||
|
default=1.0,
|
||||||
|
),
|
||||||
|
bs.IntChoiceSetting(
|
||||||
|
'Graphics',
|
||||||
|
choices=[
|
||||||
|
('Normal', 1),
|
||||||
|
('High', 2)
|
||||||
|
],
|
||||||
|
default=1),
|
||||||
|
bs.BoolSetting('Fast Movespeed', default=True),
|
||||||
|
bs.BoolSetting('Enable Jump', default=False),
|
||||||
|
bs.BoolSetting('Enable Pickup', default=False),
|
||||||
|
bs.BoolSetting('Enable Bomb', default=False),
|
||||||
|
bs.BoolSetting('Obstacles', default=False),
|
||||||
|
bs.IntChoiceSetting(
|
||||||
|
'Obstacles Shape',
|
||||||
|
choices=[
|
||||||
|
('Cube', 1),
|
||||||
|
('Sphere', 2),
|
||||||
|
('Puck', 3),
|
||||||
|
('Egg', 4),
|
||||||
|
('Random', 5),
|
||||||
|
],
|
||||||
|
default=1),
|
||||||
|
bs.BoolSetting('Obstacles Bounces Shots', default=False),
|
||||||
|
bs.IntSetting(
|
||||||
|
'Obstacle Count',
|
||||||
|
min_value=1,
|
||||||
|
default=16,
|
||||||
|
increment=1,
|
||||||
|
),
|
||||||
|
bs.BoolSetting('Random Obstacle Color', default=True),
|
||||||
|
bs.BoolSetting('Epic Mode', default=False),
|
||||||
|
]
|
||||||
|
return settings
|
||||||
|
|
||||||
|
def __init__(self, settings: dict):
|
||||||
|
super().__init__(settings)
|
||||||
|
self._scoreboard = Scoreboard()
|
||||||
|
self._score_to_win: int | None = None
|
||||||
|
self._dingsound = bs.getsound('dingSmall')
|
||||||
|
self._epic_mode = bool(settings['Epic Mode'])
|
||||||
|
self._kills_to_win_per_player = int(settings['Kills to Win Per Player'])
|
||||||
|
self._time_limit = float(settings['Time Limit'])
|
||||||
|
self._allow_negative_scores = bool(
|
||||||
|
settings.get('Allow Negative Scores', False)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Base class overrides.
|
||||||
|
self.slow_motion = self._epic_mode
|
||||||
|
self.default_music = (
|
||||||
|
bs.MusicType.EPIC if self._epic_mode else bs.MusicType.TO_THE_DEATH
|
||||||
|
)
|
||||||
|
self.settings = settings
|
||||||
|
|
||||||
|
def get_instance_description(self) -> str | Sequence:
|
||||||
|
return 'Crush ${ARG1} of your enemies.', self._score_to_win
|
||||||
|
|
||||||
|
def get_instance_description_short(self) -> str | Sequence:
|
||||||
|
return 'kill ${ARG1} enemies', self._score_to_win
|
||||||
|
|
||||||
|
def on_team_join(self, team: Team) -> None:
|
||||||
|
if self.has_begun():
|
||||||
|
self._update_scoreboard()
|
||||||
|
|
||||||
|
def on_begin(self) -> None:
|
||||||
|
super().on_begin()
|
||||||
|
self.dingsound = bs.getsound('dingSmall')
|
||||||
|
self.setup_standard_time_limit(self._time_limit)
|
||||||
|
|
||||||
|
self.drop_shield()
|
||||||
|
self.drop_shield_timer = bs.Timer(8.001, bs.WeakCall(self.drop_shield), repeat=True)
|
||||||
|
|
||||||
|
shared = SharedObjects.get()
|
||||||
|
if self.settings['Obstacles']:
|
||||||
|
count = self.settings['Obstacle Count']
|
||||||
|
map = bs.getactivity()._map.getname()
|
||||||
|
for i in range(count):
|
||||||
|
if map == 'Football Stadium':
|
||||||
|
radius = (random.uniform(-10, 1),
|
||||||
|
6,
|
||||||
|
random.uniform(-4.5, 4.5)) \
|
||||||
|
if i > count/2 else (random.uniform(10, 1), 6, random.uniform(-4.5, 4.5))
|
||||||
|
else:
|
||||||
|
radius = (random.uniform(-10, 1),
|
||||||
|
6,
|
||||||
|
random.uniform(-8, 8)) \
|
||||||
|
if i > count/2 else (random.uniform(10, 1), 6, random.uniform(-8, 8))
|
||||||
|
|
||||||
|
Obstacle(
|
||||||
|
position=radius,
|
||||||
|
graphics=self.settings['Graphics'],
|
||||||
|
random_color=self.settings['Random Obstacle Color'],
|
||||||
|
rebound=self.settings['Obstacles Bounces Shots'],
|
||||||
|
shape=int(self.settings['Obstacles Shape'])).autoretain()
|
||||||
|
|
||||||
|
if self.settings['Graphics'] == 2:
|
||||||
|
bs.getactivity().globalsnode.tint = (bs.getactivity(
|
||||||
|
).globalsnode.tint[0]-0.6, bs.getactivity().globalsnode.tint[1]-0.6, bs.getactivity().globalsnode.tint[2]-0.6)
|
||||||
|
light = bs.newnode('light', attrs={
|
||||||
|
'position': (9, 10, 0) if map == 'Football Stadium' else (6, 7, -2)
|
||||||
|
if not map == 'Rampage' else (6, 11, -2) if not map == 'The Pad' else (6, 8.5, -2),
|
||||||
|
'color': (0.4, 0.4, 0.45),
|
||||||
|
'radius': 1,
|
||||||
|
'intensity': 6,
|
||||||
|
'volume_intensity_scale': 10.0})
|
||||||
|
|
||||||
|
light2 = bs.newnode('light', attrs={
|
||||||
|
'position': (-9, 10, 0) if map == 'Football Stadium' else (-6, 7, -2)
|
||||||
|
if not map == 'Rampage' else (-6, 11, -2) if not map == 'The Pad' else (-6, 8.5, -2),
|
||||||
|
'color': (0.4, 0.4, 0.45),
|
||||||
|
'radius': 1,
|
||||||
|
'intensity': 6,
|
||||||
|
'volume_intensity_scale': 10.0})
|
||||||
|
|
||||||
|
if len(self.teams) > 0:
|
||||||
|
self._score_to_win = self.settings['Kills to Win Per Player'] * \
|
||||||
|
max(1, max(len(t.players) for t in self.teams))
|
||||||
|
else:
|
||||||
|
self._score_to_win = self.settings['Kills to Win Per Player']
|
||||||
|
self._update_scoreboard()
|
||||||
|
|
||||||
|
def drop_shield(self):
|
||||||
|
p = Powerup(
|
||||||
|
poweruptype='shield',
|
||||||
|
position=(random.uniform(-10, 10), 6, random.uniform(-5, 5))).autoretain()
|
||||||
|
|
||||||
|
bs.getsound('dingSmall').play()
|
||||||
|
|
||||||
|
p_light = bs.newnode('light', attrs={
|
||||||
|
'position': (0, 0, 0),
|
||||||
|
'color': (0.3, 0.0, 0.4),
|
||||||
|
'radius': 0.3,
|
||||||
|
'intensity': 2,
|
||||||
|
'volume_intensity_scale': 10.0})
|
||||||
|
|
||||||
|
p.node.connectattr('position', p_light, 'position')
|
||||||
|
|
||||||
|
bs.animate(p_light, 'intensity', {0: 2, 8000: 0})
|
||||||
|
|
||||||
|
def check_exists():
|
||||||
|
if p is None or p.node.exists() == False:
|
||||||
|
delete_light()
|
||||||
|
del_checker()
|
||||||
|
|
||||||
|
self._checker = bs.Timer(0.1, babase.Call(check_exists), repeat=True)
|
||||||
|
|
||||||
|
def del_checker():
|
||||||
|
if self._checker is not None:
|
||||||
|
self._checker = None
|
||||||
|
|
||||||
|
def delete_light():
|
||||||
|
if p_light.exists():
|
||||||
|
p_light.delete()
|
||||||
|
|
||||||
|
bs.timer(6.9, babase.Call(del_checker))
|
||||||
|
bs.timer(7.0, babase.Call(delete_light))
|
||||||
|
|
||||||
|
def spawn_player(self, player: bs.Player):
|
||||||
|
spaz = self.spawn_player_spaz(player)
|
||||||
|
QuakeBallFactory().give(spaz)
|
||||||
|
spaz.connect_controls_to_player(
|
||||||
|
enable_jump=self.settings['Enable Jump'],
|
||||||
|
enable_punch=True,
|
||||||
|
enable_pickup=self.settings['Enable Pickup'],
|
||||||
|
enable_bomb=self.settings['Enable Bomb'],
|
||||||
|
enable_run=True,
|
||||||
|
enable_fly=False)
|
||||||
|
|
||||||
|
if self.settings['Fast Movespeed']:
|
||||||
|
spaz.node.hockey = True
|
||||||
|
spaz.spaz_light = bs.newnode('light', attrs={
|
||||||
|
'position': (0, 0, 0),
|
||||||
|
'color': spaz.node.color,
|
||||||
|
'radius': 0.12,
|
||||||
|
'intensity': 1,
|
||||||
|
'volume_intensity_scale': 10.0})
|
||||||
|
|
||||||
|
spaz.node.connectattr('position', spaz.spaz_light, 'position')
|
||||||
|
|
||||||
|
def handlemessage(self, msg: Any) -> Any:
|
||||||
|
|
||||||
|
if isinstance(msg, bs.PlayerDiedMessage):
|
||||||
|
|
||||||
|
# Augment standard behavior.
|
||||||
|
super().handlemessage(msg)
|
||||||
|
|
||||||
|
player = msg.getplayer(Player)
|
||||||
|
self.respawn_player(player)
|
||||||
|
|
||||||
|
killer = msg.getkillerplayer(Player)
|
||||||
|
if hasattr(player.actor, 'spaz_light'):
|
||||||
|
player.actor.spaz_light.delete()
|
||||||
|
if killer is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Handle team-kills.
|
||||||
|
if killer.team is player.team:
|
||||||
|
|
||||||
|
# In free-for-all, killing yourself loses you a point.
|
||||||
|
if isinstance(self.session, bs.FreeForAllSession):
|
||||||
|
new_score = player.team.score - 1
|
||||||
|
if not self._allow_negative_scores:
|
||||||
|
new_score = max(0, new_score)
|
||||||
|
player.team.score = new_score
|
||||||
|
|
||||||
|
# In teams-mode it gives a point to the other team.
|
||||||
|
else:
|
||||||
|
self._dingsound.play()
|
||||||
|
for team in self.teams:
|
||||||
|
if team is not killer.team:
|
||||||
|
team.score += 1
|
||||||
|
|
||||||
|
# Killing someone on another team nets a kill.
|
||||||
|
else:
|
||||||
|
killer.team.score += 1
|
||||||
|
self._dingsound.play()
|
||||||
|
|
||||||
|
# In FFA show scores since its hard to find on the scoreboard.
|
||||||
|
if isinstance(killer.actor, PlayerSpaz) and killer.actor:
|
||||||
|
killer.actor.set_score_text(
|
||||||
|
str(killer.team.score) + '/' + str(self._score_to_win),
|
||||||
|
color=killer.team.color,
|
||||||
|
flash=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
self._update_scoreboard()
|
||||||
|
|
||||||
|
# If someone has won, set a timer to end shortly.
|
||||||
|
# (allows the dust to clear and draws to occur if deaths are
|
||||||
|
# close enough)
|
||||||
|
assert self._score_to_win is not None
|
||||||
|
if any(team.score >= self._score_to_win for team in self.teams):
|
||||||
|
bs.timer(0.5, self.end_game)
|
||||||
|
|
||||||
|
else:
|
||||||
|
return super().handlemessage(msg)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _update_scoreboard(self) -> None:
|
||||||
|
for team in self.teams:
|
||||||
|
self._scoreboard.set_team_value(
|
||||||
|
team, team.score, self._score_to_win
|
||||||
|
)
|
||||||
|
|
||||||
|
def end_game(self) -> None:
|
||||||
|
results = bs.GameResults()
|
||||||
|
for team in self.teams:
|
||||||
|
results.set_team_score(team, team.score)
|
||||||
|
self.end(results=results)
|
||||||
|
|
||||||
|
|
||||||
|
class Obstacle(bs.Actor):
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
position: tuple(float, float, float),
|
||||||
|
graphics: bool,
|
||||||
|
random_color: bool,
|
||||||
|
rebound: bool,
|
||||||
|
shape: int) -> None:
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
shared = SharedObjects.get()
|
||||||
|
if shape == 1:
|
||||||
|
mesh = 'tnt'
|
||||||
|
body = 'crate'
|
||||||
|
elif shape == 2:
|
||||||
|
mesh = 'bomb'
|
||||||
|
body = 'sphere'
|
||||||
|
elif shape == 3:
|
||||||
|
mesh = 'puck'
|
||||||
|
body = 'puck'
|
||||||
|
elif shape == 4:
|
||||||
|
mesh = 'egg'
|
||||||
|
body = 'capsule'
|
||||||
|
elif shape == 5:
|
||||||
|
pair = random.choice([
|
||||||
|
{'mesh': 'tnt', 'body': 'crate'},
|
||||||
|
{'mesh': 'bomb', 'body': 'sphere'},
|
||||||
|
{'mesh': 'puckModel', 'body': 'puck'},
|
||||||
|
{'mesh': 'egg', 'body': 'capsule'}
|
||||||
|
])
|
||||||
|
mesh = pair['mesh']
|
||||||
|
body = pair['body']
|
||||||
|
|
||||||
|
self.node = bs.newnode('prop', delegate=self, attrs={
|
||||||
|
'position': position,
|
||||||
|
'mesh': bs.getmesh(mesh),
|
||||||
|
'body': body,
|
||||||
|
'body_scale': 1.3,
|
||||||
|
'mesh_scale': 1.3,
|
||||||
|
'reflection': 'powerup',
|
||||||
|
'reflection_scale': [0.7],
|
||||||
|
'color_texture': bs.gettexture('bunnyColor'),
|
||||||
|
'materials': [shared.footing_material if rebound else shared.object_material,
|
||||||
|
shared.footing_material]})
|
||||||
|
|
||||||
|
if graphics == 2:
|
||||||
|
self.light_node = bs.newnode('light', attrs={
|
||||||
|
'position': (0, 0, 0),
|
||||||
|
'color': ((0.8, 0.2, 0.2) if i < count/2 else (0.2, 0.2, 0.8))
|
||||||
|
if not random_color else ((random.uniform(0, 1.1), random.uniform(0, 1.1), random.uniform(0, 1.1))),
|
||||||
|
'radius': 0.2,
|
||||||
|
'intensity': 1,
|
||||||
|
'volume_intensity_scale': 10.0})
|
||||||
|
|
||||||
|
self.node.connectattr('position', self.light_node, 'position')
|
||||||
|
|
||||||
|
def handlemessage(self, m):
|
||||||
|
if isinstance(m, bs.DieMessage):
|
||||||
|
if self.node.exists():
|
||||||
|
if hasattr(self, 'light_node'):
|
||||||
|
self.light_node.delete()
|
||||||
|
self.node.delete()
|
||||||
|
|
||||||
|
elif isinstance(m, bs.OutOfBoundsMessage):
|
||||||
|
if self.node.exists():
|
||||||
|
self.handlemessage(bs.DieMessage())
|
||||||
|
|
||||||
|
elif isinstance(m, bs.HitMessage):
|
||||||
|
self.node.handlemessage('impulse', m.pos[0], m.pos[1], m.pos[2],
|
||||||
|
m.velocity[0], m.velocity[1], m.velocity[2],
|
||||||
|
m.magnitude, m.velocity_magnitude, m.radius, 0,
|
||||||
|
m.velocity[0], m.velocity[1], m.velocity[2])
|
||||||
|
|
@ -2,18 +2,20 @@
|
||||||
# BY Stary_Agent
|
# BY Stary_Agent
|
||||||
"""Hockey game and support classes."""
|
"""Hockey game and support classes."""
|
||||||
|
|
||||||
# ba_meta require api 7
|
# ba_meta require api 8
|
||||||
# (see https://ballistica.net/wiki/meta-tag-system)
|
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import ba
|
import babase
|
||||||
from bastd.actor.playerspaz import PlayerSpaz
|
import bauiv1 as bui
|
||||||
from bastd.actor.scoreboard import Scoreboard
|
import bascenev1 as bs
|
||||||
from bastd.actor.powerupbox import PowerupBoxFactory
|
from bascenev1lib.actor.playerspaz import PlayerSpaz
|
||||||
from bastd.gameutils import SharedObjects
|
from bascenev1lib.actor.scoreboard import Scoreboard
|
||||||
|
from bascenev1lib.actor.powerupbox import PowerupBoxFactory
|
||||||
|
from bascenev1lib.gameutils import SharedObjects
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any, Sequence, Dict, Type, List, Optional, Union
|
from typing import Any, Sequence, Dict, Type, List, Optional, Union
|
||||||
|
|
@ -26,7 +28,7 @@ class PuckDiedMessage:
|
||||||
self.puck = puck
|
self.puck = puck
|
||||||
|
|
||||||
|
|
||||||
class Puck(ba.Actor):
|
class Puck(bs.Actor):
|
||||||
"""A lovely giant hockey puck."""
|
"""A lovely giant hockey puck."""
|
||||||
|
|
||||||
def __init__(self, position: Sequence[float] = (0.0, 1.0, 0.0)):
|
def __init__(self, position: Sequence[float] = (0.0, 1.0, 0.0)):
|
||||||
|
|
@ -41,10 +43,10 @@ class Puck(ba.Actor):
|
||||||
assert activity is not None
|
assert activity is not None
|
||||||
assert isinstance(activity, HockeyGame)
|
assert isinstance(activity, HockeyGame)
|
||||||
pmats = [shared.object_material, activity.puck_material]
|
pmats = [shared.object_material, activity.puck_material]
|
||||||
self.node = ba.newnode('prop',
|
self.node = bs.newnode('prop',
|
||||||
delegate=self,
|
delegate=self,
|
||||||
attrs={
|
attrs={
|
||||||
'model': activity.puck_model,
|
'mesh': activity.puck_model,
|
||||||
'color_texture': activity.puck_tex,
|
'color_texture': activity.puck_tex,
|
||||||
'body': 'sphere',
|
'body': 'sphere',
|
||||||
'reflection': 'soft',
|
'reflection': 'soft',
|
||||||
|
|
@ -54,10 +56,10 @@ class Puck(ba.Actor):
|
||||||
'position': self._spawn_pos,
|
'position': self._spawn_pos,
|
||||||
'materials': pmats
|
'materials': pmats
|
||||||
})
|
})
|
||||||
ba.animate(self.node, 'model_scale', {0: 0, 0.2: 1.3, 0.26: 1})
|
bs.animate(self.node, 'mesh_scale', {0: 0, 0.2: 1.3, 0.26: 1})
|
||||||
|
|
||||||
def handlemessage(self, msg: Any) -> Any:
|
def handlemessage(self, msg: Any) -> Any:
|
||||||
if isinstance(msg, ba.DieMessage):
|
if isinstance(msg, bs.DieMessage):
|
||||||
assert self.node
|
assert self.node
|
||||||
self.node.delete()
|
self.node.delete()
|
||||||
activity = self._activity()
|
activity = self._activity()
|
||||||
|
|
@ -65,11 +67,11 @@ class Puck(ba.Actor):
|
||||||
activity.handlemessage(PuckDiedMessage(self))
|
activity.handlemessage(PuckDiedMessage(self))
|
||||||
|
|
||||||
# If we go out of bounds, move back to where we started.
|
# If we go out of bounds, move back to where we started.
|
||||||
elif isinstance(msg, ba.OutOfBoundsMessage):
|
elif isinstance(msg, bs.OutOfBoundsMessage):
|
||||||
assert self.node
|
assert self.node
|
||||||
self.node.position = self._spawn_pos
|
self.node.position = self._spawn_pos
|
||||||
|
|
||||||
elif isinstance(msg, ba.HitMessage):
|
elif isinstance(msg, bs.HitMessage):
|
||||||
assert self.node
|
assert self.node
|
||||||
assert msg.force_direction is not None
|
assert msg.force_direction is not None
|
||||||
self.node.handlemessage(
|
self.node.handlemessage(
|
||||||
|
|
@ -90,31 +92,31 @@ class Puck(ba.Actor):
|
||||||
super().handlemessage(msg)
|
super().handlemessage(msg)
|
||||||
|
|
||||||
|
|
||||||
class Player(ba.Player['Team']):
|
class Player(bs.Player['Team']):
|
||||||
"""Our player type for this game."""
|
"""Our player type for this game."""
|
||||||
|
|
||||||
|
|
||||||
class Team(ba.Team[Player]):
|
class Team(bs.Team[Player]):
|
||||||
"""Our team type for this game."""
|
"""Our team type for this game."""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.score = 0
|
self.score = 0
|
||||||
|
|
||||||
|
|
||||||
# ba_meta export game
|
# ba_meta export bascenev1.GameActivity
|
||||||
class HockeyGame(ba.TeamGameActivity[Player, Team]):
|
class HockeyGame(bs.TeamGameActivity[Player, Team]):
|
||||||
"""Ice hockey game."""
|
"""Ice hockey game."""
|
||||||
|
|
||||||
name = 'Epic Soccer'
|
name = 'Epic Soccer'
|
||||||
description = 'Score some goals.'
|
description = 'Score some goals.'
|
||||||
available_settings = [
|
available_settings = [
|
||||||
ba.IntSetting(
|
bs.IntSetting(
|
||||||
'Score to Win',
|
'Score to Win',
|
||||||
min_value=1,
|
min_value=1,
|
||||||
default=1,
|
default=1,
|
||||||
increment=1,
|
increment=1,
|
||||||
),
|
),
|
||||||
ba.IntChoiceSetting(
|
bs.IntChoiceSetting(
|
||||||
'Time Limit',
|
'Time Limit',
|
||||||
choices=[
|
choices=[
|
||||||
('None', 0),
|
('None', 0),
|
||||||
|
|
@ -126,7 +128,7 @@ class HockeyGame(ba.TeamGameActivity[Player, Team]):
|
||||||
],
|
],
|
||||||
default=0,
|
default=0,
|
||||||
),
|
),
|
||||||
ba.FloatChoiceSetting(
|
bs.FloatChoiceSetting(
|
||||||
'Respawn Times',
|
'Respawn Times',
|
||||||
choices=[
|
choices=[
|
||||||
('Shorter', 0.1),
|
('Shorter', 0.1),
|
||||||
|
|
@ -138,31 +140,32 @@ class HockeyGame(ba.TeamGameActivity[Player, Team]):
|
||||||
default=1.0,
|
default=1.0,
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
default_music = ba.MusicType.HOCKEY
|
default_music = bs.MusicType.HOCKEY
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
|
def supports_session_type(cls, sessiontype: Type[bs.Session]) -> bool:
|
||||||
return issubclass(sessiontype, ba.DualTeamSession)
|
return issubclass(sessiontype, bs.DualTeamSession)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
|
def get_supported_maps(cls, sessiontype: Type[bs.Session]) -> List[str]:
|
||||||
return ba.getmaps('football')
|
assert babase.app.classic is not None
|
||||||
|
return babase.app.classic.getmaps('football')
|
||||||
|
|
||||||
def __init__(self, settings: dict):
|
def __init__(self, settings: dict):
|
||||||
super().__init__(settings)
|
super().__init__(settings)
|
||||||
shared = SharedObjects.get()
|
shared = SharedObjects.get()
|
||||||
self.slow_motion = True
|
self.slow_motion = True
|
||||||
self._scoreboard = Scoreboard()
|
self._scoreboard = Scoreboard()
|
||||||
self._cheer_sound = ba.getsound('cheer')
|
self._cheer_sound = bui.getsound('cheer')
|
||||||
self._chant_sound = ba.getsound('crowdChant')
|
self._chant_sound = bui.getsound('crowdChant')
|
||||||
self._foghorn_sound = ba.getsound('foghorn')
|
self._foghorn_sound = bui.getsound('foghorn')
|
||||||
self._swipsound = ba.getsound('swip')
|
self._swipsound = bui.getsound('swip')
|
||||||
self._whistle_sound = ba.getsound('refWhistle')
|
self._whistle_sound = bui.getsound('refWhistle')
|
||||||
self.puck_model = ba.getmodel('bomb')
|
self.puck_model = bs.getmesh('bomb')
|
||||||
self.puck_tex = ba.gettexture('landMine')
|
self.puck_tex = bs.gettexture('landMine')
|
||||||
self.puck_scored_tex = ba.gettexture('landMineLit')
|
self.puck_scored_tex = bs.gettexture('landMineLit')
|
||||||
self._puck_sound = ba.getsound('metalHit')
|
self._puck_sound = bs.getsound('metalHit')
|
||||||
self.puck_material = ba.Material()
|
self.puck_material = bs.Material()
|
||||||
self.puck_material.add_actions(actions=(('modify_part_collision',
|
self.puck_material.add_actions(actions=(('modify_part_collision',
|
||||||
'friction', 0.5)))
|
'friction', 0.5)))
|
||||||
self.puck_material.add_actions(conditions=('they_have_material',
|
self.puck_material.add_actions(conditions=('they_have_material',
|
||||||
|
|
@ -193,15 +196,15 @@ class HockeyGame(ba.TeamGameActivity[Player, Team]):
|
||||||
conditions=('they_have_material',
|
conditions=('they_have_material',
|
||||||
PowerupBoxFactory.get().powerup_material),
|
PowerupBoxFactory.get().powerup_material),
|
||||||
actions=(('modify_part_collision', 'physical', False),
|
actions=(('modify_part_collision', 'physical', False),
|
||||||
('message', 'their_node', 'at_connect', ba.DieMessage())))
|
('message', 'their_node', 'at_connect', bs.DieMessage())))
|
||||||
self._score_region_material = ba.Material()
|
self._score_region_material = bs.Material()
|
||||||
self._score_region_material.add_actions(
|
self._score_region_material.add_actions(
|
||||||
conditions=('they_have_material', self.puck_material),
|
conditions=('they_have_material', self.puck_material),
|
||||||
actions=(('modify_part_collision', 'collide',
|
actions=(('modify_part_collision', 'collide',
|
||||||
True), ('modify_part_collision', 'physical', False),
|
True), ('modify_part_collision', 'physical', False),
|
||||||
('call', 'at_connect', self._handle_score)))
|
('call', 'at_connect', self._handle_score)))
|
||||||
self._puck_spawn_pos: Optional[Sequence[float]] = None
|
self._puck_spawn_pos: Optional[Sequence[float]] = None
|
||||||
self._score_regions: Optional[List[ba.NodeActor]] = None
|
self._score_regions: Optional[List[bs.NodeActor]] = None
|
||||||
self._puck: Optional[Puck] = None
|
self._puck: Optional[Puck] = None
|
||||||
self._score_to_win = int(settings['Score to Win'])
|
self._score_to_win = int(settings['Score to Win'])
|
||||||
self._time_limit = float(settings['Time Limit'])
|
self._time_limit = float(settings['Time Limit'])
|
||||||
|
|
@ -228,8 +231,8 @@ class HockeyGame(ba.TeamGameActivity[Player, Team]):
|
||||||
defs = self.map.defs
|
defs = self.map.defs
|
||||||
self._score_regions = []
|
self._score_regions = []
|
||||||
self._score_regions.append(
|
self._score_regions.append(
|
||||||
ba.NodeActor(
|
bs.NodeActor(
|
||||||
ba.newnode('region',
|
bs.newnode('region',
|
||||||
attrs={
|
attrs={
|
||||||
'position': defs.boxes['goal1'][0:3],
|
'position': defs.boxes['goal1'][0:3],
|
||||||
'scale': defs.boxes['goal1'][6:9],
|
'scale': defs.boxes['goal1'][6:9],
|
||||||
|
|
@ -237,8 +240,8 @@ class HockeyGame(ba.TeamGameActivity[Player, Team]):
|
||||||
'materials': [self._score_region_material]
|
'materials': [self._score_region_material]
|
||||||
})))
|
})))
|
||||||
self._score_regions.append(
|
self._score_regions.append(
|
||||||
ba.NodeActor(
|
bs.NodeActor(
|
||||||
ba.newnode('region',
|
bs.newnode('region',
|
||||||
attrs={
|
attrs={
|
||||||
'position': defs.boxes['goal2'][0:3],
|
'position': defs.boxes['goal2'][0:3],
|
||||||
'scale': defs.boxes['goal2'][6:9],
|
'scale': defs.boxes['goal2'][6:9],
|
||||||
|
|
@ -246,19 +249,19 @@ class HockeyGame(ba.TeamGameActivity[Player, Team]):
|
||||||
'materials': [self._score_region_material]
|
'materials': [self._score_region_material]
|
||||||
})))
|
})))
|
||||||
self._update_scoreboard()
|
self._update_scoreboard()
|
||||||
ba.playsound(self._chant_sound)
|
self._chant_sound.play()
|
||||||
|
|
||||||
def on_team_join(self, team: Team) -> None:
|
def on_team_join(self, team: Team) -> None:
|
||||||
self._update_scoreboard()
|
self._update_scoreboard()
|
||||||
|
|
||||||
def _handle_puck_player_collide(self) -> None:
|
def _handle_puck_player_collide(self) -> None:
|
||||||
collision = ba.getcollision()
|
collision = bs.getcollision()
|
||||||
try:
|
try:
|
||||||
puck = collision.sourcenode.getdelegate(Puck, True)
|
puck = collision.sourcenode.getdelegate(Puck, True)
|
||||||
player = collision.opposingnode.getdelegate(PlayerSpaz,
|
player = collision.opposingnode.getdelegate(PlayerSpaz,
|
||||||
True).getplayer(
|
True).getplayer(
|
||||||
Player, True)
|
Player, True)
|
||||||
except ba.NotFoundError:
|
except bs.NotFoundError:
|
||||||
return
|
return
|
||||||
|
|
||||||
puck.last_players_to_touch[player.team.id] = player
|
puck.last_players_to_touch[player.team.id] = player
|
||||||
|
|
@ -277,7 +280,7 @@ class HockeyGame(ba.TeamGameActivity[Player, Team]):
|
||||||
if self._puck.scored:
|
if self._puck.scored:
|
||||||
return
|
return
|
||||||
|
|
||||||
region = ba.getcollision().sourcenode
|
region = bs.getcollision().sourcenode
|
||||||
index = 0
|
index = 0
|
||||||
for index in range(len(self._score_regions)):
|
for index in range(len(self._score_regions)):
|
||||||
if region == self._score_regions[index].node:
|
if region == self._score_regions[index].node:
|
||||||
|
|
@ -291,7 +294,7 @@ class HockeyGame(ba.TeamGameActivity[Player, Team]):
|
||||||
# Tell all players to celebrate.
|
# Tell all players to celebrate.
|
||||||
for player in team.players:
|
for player in team.players:
|
||||||
if player.actor:
|
if player.actor:
|
||||||
player.actor.handlemessage(ba.CelebrateMessage(2.0))
|
player.actor.handlemessage(bs.CelebrateMessage(2.0))
|
||||||
|
|
||||||
# If we've got the player from the scoring team that last
|
# If we've got the player from the scoring team that last
|
||||||
# touched us, give them points.
|
# touched us, give them points.
|
||||||
|
|
@ -306,30 +309,30 @@ class HockeyGame(ba.TeamGameActivity[Player, Team]):
|
||||||
if team.score >= self._score_to_win:
|
if team.score >= self._score_to_win:
|
||||||
self.end_game()
|
self.end_game()
|
||||||
|
|
||||||
ba.playsound(self._foghorn_sound)
|
self._foghorn_sound.play()
|
||||||
ba.playsound(self._cheer_sound)
|
self._cheer_sound.play()
|
||||||
|
|
||||||
self._puck.scored = True
|
self._puck.scored = True
|
||||||
|
|
||||||
# Change puck texture to something cool
|
# Change puck texture to something cool
|
||||||
self._puck.node.color_texture = self.puck_scored_tex
|
self._puck.node.color_texture = self.puck_scored_tex
|
||||||
# Kill the puck (it'll respawn itself shortly).
|
# Kill the puck (it'll respawn itself shortly).
|
||||||
ba.timer(1.0, self._kill_puck)
|
bs.timer(1.0, self._kill_puck)
|
||||||
|
|
||||||
light = ba.newnode('light',
|
light = bs.newnode('light',
|
||||||
attrs={
|
attrs={
|
||||||
'position': ba.getcollision().position,
|
'position': bs.getcollision().position,
|
||||||
'height_attenuated': False,
|
'height_attenuated': False,
|
||||||
'color': (1, 0, 0)
|
'color': (1, 0, 0)
|
||||||
})
|
})
|
||||||
ba.animate(light, 'intensity', {0: 0, 0.5: 1, 1.0: 0}, loop=True)
|
bs.animate(light, 'intensity', {0: 0, 0.5: 1, 1.0: 0}, loop=True)
|
||||||
ba.timer(1.0, light.delete)
|
bs.timer(1.0, light.delete)
|
||||||
|
|
||||||
ba.cameraflash(duration=10.0)
|
bs.cameraflash(duration=10.0)
|
||||||
self._update_scoreboard()
|
self._update_scoreboard()
|
||||||
|
|
||||||
def end_game(self) -> None:
|
def end_game(self) -> None:
|
||||||
results = ba.GameResults()
|
results = bs.GameResults()
|
||||||
for team in self.teams:
|
for team in self.teams:
|
||||||
results.set_team_score(team, team.score)
|
results.set_team_score(team, team.score)
|
||||||
self.end(results=results)
|
self.end(results=results)
|
||||||
|
|
@ -342,7 +345,7 @@ class HockeyGame(ba.TeamGameActivity[Player, Team]):
|
||||||
def handlemessage(self, msg: Any) -> Any:
|
def handlemessage(self, msg: Any) -> Any:
|
||||||
|
|
||||||
# Respawn dead players if they're still in the game.
|
# Respawn dead players if they're still in the game.
|
||||||
if isinstance(msg, ba.PlayerDiedMessage):
|
if isinstance(msg, bs.PlayerDiedMessage):
|
||||||
# Augment standard behavior...
|
# Augment standard behavior...
|
||||||
super().handlemessage(msg)
|
super().handlemessage(msg)
|
||||||
self.respawn_player(msg.getplayer(Player))
|
self.respawn_player(msg.getplayer(Player))
|
||||||
|
|
@ -350,23 +353,23 @@ class HockeyGame(ba.TeamGameActivity[Player, Team]):
|
||||||
# Respawn dead pucks.
|
# Respawn dead pucks.
|
||||||
elif isinstance(msg, PuckDiedMessage):
|
elif isinstance(msg, PuckDiedMessage):
|
||||||
if not self.has_ended():
|
if not self.has_ended():
|
||||||
ba.timer(3.0, self._spawn_puck)
|
bs.timer(3.0, self._spawn_puck)
|
||||||
else:
|
else:
|
||||||
super().handlemessage(msg)
|
super().handlemessage(msg)
|
||||||
|
|
||||||
def _flash_puck_spawn(self) -> None:
|
def _flash_puck_spawn(self) -> None:
|
||||||
light = ba.newnode('light',
|
light = bs.newnode('light',
|
||||||
attrs={
|
attrs={
|
||||||
'position': self._puck_spawn_pos,
|
'position': self._puck_spawn_pos,
|
||||||
'height_attenuated': False,
|
'height_attenuated': False,
|
||||||
'color': (1, 0, 0)
|
'color': (1, 0, 0)
|
||||||
})
|
})
|
||||||
ba.animate(light, 'intensity', {0.0: 0, 0.25: 1, 0.5: 0}, loop=True)
|
bs.animate(light, 'intensity', {0.0: 0, 0.25: 1, 0.5: 0}, loop=True)
|
||||||
ba.timer(1.0, light.delete)
|
bs.timer(1.0, light.delete)
|
||||||
|
|
||||||
def _spawn_puck(self) -> None:
|
def _spawn_puck(self) -> None:
|
||||||
ba.playsound(self._swipsound)
|
self._swipsound.play()
|
||||||
ba.playsound(self._whistle_sound)
|
self._whistle_sound.play()
|
||||||
self._flash_puck_spawn()
|
self._flash_puck_spawn()
|
||||||
assert self._puck_spawn_pos is not None
|
assert self._puck_spawn_pos is not None
|
||||||
self._puck = Puck(position=self._puck_spawn_pos)
|
self._puck = Puck(position=self._puck_spawn_pos)
|
||||||
|
|
|
||||||
602
plugins/minigames/super_duel.py
Normal file
602
plugins/minigames/super_duel.py
Normal file
|
|
@ -0,0 +1,602 @@
|
||||||
|
"""New Duel / Created by: byANG3L"""
|
||||||
|
|
||||||
|
# ba_meta require api 8
|
||||||
|
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
import babase
|
||||||
|
import bauiv1 as bui
|
||||||
|
import bascenev1 as bs
|
||||||
|
import random
|
||||||
|
from bascenev1lib.actor.playerspaz import PlayerSpaz
|
||||||
|
from bascenev1lib.actor.scoreboard import Scoreboard
|
||||||
|
from bascenev1lib.game.elimination import Icon
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from typing import Any, Type, List, Dict, Tuple, Union, Sequence, Optional
|
||||||
|
|
||||||
|
|
||||||
|
class SuperSpaz(PlayerSpaz):
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
player: bs.Player,
|
||||||
|
color: Sequence[float] = (1.0, 1.0, 1.0),
|
||||||
|
highlight: Sequence[float] = (0.5, 0.5, 0.5),
|
||||||
|
character: str = 'Spaz',
|
||||||
|
super_punch: bool = False,
|
||||||
|
powerups_expire: bool = True):
|
||||||
|
super().__init__(player=player,
|
||||||
|
color=color,
|
||||||
|
highlight=highlight,
|
||||||
|
character=character,
|
||||||
|
powerups_expire=powerups_expire)
|
||||||
|
self._super_punch = super_punch
|
||||||
|
|
||||||
|
def handlemessage(self, msg: Any) -> Any:
|
||||||
|
from bascenev1lib.actor.spaz import PunchHitMessage
|
||||||
|
from bascenev1lib.actor.bomb import Blast
|
||||||
|
if isinstance(msg, PunchHitMessage):
|
||||||
|
super().handlemessage(msg)
|
||||||
|
node = bs.getcollision().opposingnode
|
||||||
|
if self._super_punch:
|
||||||
|
if node.getnodetype() == 'spaz':
|
||||||
|
if not node.frozen:
|
||||||
|
node.frozen = True
|
||||||
|
node.handlemessage(babase.FreezeMessage())
|
||||||
|
bs.getsound('freeze').play()
|
||||||
|
bs.getsound('superPunch').play()
|
||||||
|
bs.getsound('punchStrong02').play()
|
||||||
|
Blast(position=node.position,
|
||||||
|
velocity=node.velocity,
|
||||||
|
blast_radius=0.0,
|
||||||
|
blast_type='normal').autoretain()
|
||||||
|
else:
|
||||||
|
return super().handlemessage(msg)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class Player(bs.Player['Team']):
|
||||||
|
"""Our player type for this game."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.icons: List[Icon] = []
|
||||||
|
self.in_game: bool = False
|
||||||
|
self.playervs1: bool = False
|
||||||
|
self.playervs2: bool = False
|
||||||
|
self.light: bool = False
|
||||||
|
|
||||||
|
|
||||||
|
class Team(bs.Team[Player]):
|
||||||
|
"""Our team type for this game."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.score = 0
|
||||||
|
|
||||||
|
|
||||||
|
lang = bs.app.lang.language
|
||||||
|
if lang == 'Spanish':
|
||||||
|
enable_powerups = 'Habilitar Potenciadores'
|
||||||
|
night_mode = 'Modo Noche'
|
||||||
|
fight_delay = 'Tiempo entre Pelea'
|
||||||
|
very_fast = 'Muy Rápido'
|
||||||
|
fast = 'Rápido'
|
||||||
|
normal = 'Normal'
|
||||||
|
slow = 'Lento'
|
||||||
|
very_slow = 'Muy Lento'
|
||||||
|
none = 'Ninguno'
|
||||||
|
super_punch = 'Super Golpe'
|
||||||
|
box_mode = 'Modo Caja'
|
||||||
|
boxing_gloves = 'Guantes de Boxeo'
|
||||||
|
else:
|
||||||
|
enable_powerups = 'Enable Powerups'
|
||||||
|
night_mode = 'Night Mode'
|
||||||
|
fight_delay = 'Fight Delay'
|
||||||
|
very_fast = 'Very Fast'
|
||||||
|
fast = 'Fast'
|
||||||
|
normal = 'Normal'
|
||||||
|
slow = 'Slow'
|
||||||
|
very_slow = 'Very Slow'
|
||||||
|
super_punch = 'Super Punch'
|
||||||
|
box_mode = 'Box Mode'
|
||||||
|
boxing_gloves = 'Boxing Gloves'
|
||||||
|
|
||||||
|
# ba_meta export bascenev1.GameActivity
|
||||||
|
|
||||||
|
|
||||||
|
class NewDuelGame(bs.TeamGameActivity[Player, Team]):
|
||||||
|
"""A game type based on acquiring kills."""
|
||||||
|
|
||||||
|
name = 'Duel'
|
||||||
|
description = 'Kill a set number of enemies to win.'
|
||||||
|
|
||||||
|
# Print messages when players die since it matters here.
|
||||||
|
announce_player_deaths = True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_available_settings(
|
||||||
|
cls, sessiontype: Type[bs.Session]) -> List[babase.Setting]:
|
||||||
|
settings = [
|
||||||
|
bs.IntSetting(
|
||||||
|
'Kills to Win Per Player',
|
||||||
|
min_value=1,
|
||||||
|
default=5,
|
||||||
|
increment=1,
|
||||||
|
),
|
||||||
|
bs.IntChoiceSetting(
|
||||||
|
'Time Limit',
|
||||||
|
choices=[
|
||||||
|
('None', 0),
|
||||||
|
('1 Minute', 60),
|
||||||
|
('2 Minutes', 120),
|
||||||
|
('5 Minutes', 300),
|
||||||
|
('10 Minutes', 600),
|
||||||
|
('20 Minutes', 1200),
|
||||||
|
],
|
||||||
|
default=0,
|
||||||
|
),
|
||||||
|
bs.BoolSetting(enable_powerups, default=False),
|
||||||
|
bs.BoolSetting(boxing_gloves, default=False),
|
||||||
|
bs.BoolSetting(night_mode, default=False),
|
||||||
|
bs.BoolSetting(super_punch, default=False),
|
||||||
|
bs.BoolSetting(box_mode, default=False),
|
||||||
|
bs.BoolSetting('Epic Mode', default=False),
|
||||||
|
bs.BoolSetting('Allow Negative Scores', default=False),
|
||||||
|
]
|
||||||
|
return settings
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def supports_session_type(cls, sessiontype: Type[bs.Session]) -> bool:
|
||||||
|
return (issubclass(sessiontype, bs.FreeForAllSession))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_supported_maps(cls, sessiontype: Type[bs.Session]) -> List[str]:
|
||||||
|
return bs.app.classic.getmaps('melee')
|
||||||
|
|
||||||
|
def __init__(self, settings: dict):
|
||||||
|
super().__init__(settings)
|
||||||
|
self._scoreboard = Scoreboard()
|
||||||
|
self._score_to_win: Optional[int] = None
|
||||||
|
self._dingsound = bs.getsound('dingSmall')
|
||||||
|
self._epic_mode = bool(settings['Epic Mode'])
|
||||||
|
self._kills_to_win_per_player = int(
|
||||||
|
settings['Kills to Win Per Player'])
|
||||||
|
self._enable_powerups = bool(settings[enable_powerups])
|
||||||
|
self._night_mode = bool(settings[night_mode])
|
||||||
|
self._fight_delay: float = 0
|
||||||
|
self._time_limit = float(settings['Time Limit'])
|
||||||
|
self._allow_negative_scores = bool(
|
||||||
|
settings.get('Allow Negative Scores', False))
|
||||||
|
self._super_punch = bool(settings[super_punch])
|
||||||
|
self._box_mode = bool(settings[box_mode])
|
||||||
|
self._boxing_gloves = bool(settings[boxing_gloves])
|
||||||
|
self._vs_text: Optional[bs.Actor] = None
|
||||||
|
self.spawn_order: List[Player] = []
|
||||||
|
self._players_vs_1: bool = False
|
||||||
|
self._players_vs_2: bool = False
|
||||||
|
self._first_countdown: bool = True
|
||||||
|
self._count_1 = bs.getsound('announceOne')
|
||||||
|
self._count_2 = bs.getsound('announceTwo')
|
||||||
|
self._count_3 = bs.getsound('announceThree')
|
||||||
|
self._boxing_bell = bs.getsound('boxingBell')
|
||||||
|
|
||||||
|
# Base class overrides.
|
||||||
|
self.slow_motion = self._epic_mode
|
||||||
|
self.default_music = (bs.MusicType.EPIC if self._epic_mode else
|
||||||
|
bs.MusicType.TO_THE_DEATH)
|
||||||
|
|
||||||
|
def get_instance_description(self) -> Union[str, Sequence]:
|
||||||
|
return 'Crush ${ARG1} of your enemies.', self._score_to_win
|
||||||
|
|
||||||
|
def get_instance_description_short(self) -> Union[str, Sequence]:
|
||||||
|
return 'kill ${ARG1} enemies', self._score_to_win
|
||||||
|
|
||||||
|
def on_player_join(self, player: Player) -> None:
|
||||||
|
self.spawn_order.append(player)
|
||||||
|
self._update_order()
|
||||||
|
|
||||||
|
def on_player_leave(self, player: Player) -> None:
|
||||||
|
super().on_player_leave(player)
|
||||||
|
player.icons = []
|
||||||
|
if player.playervs1:
|
||||||
|
player.playervs1 = False
|
||||||
|
self._players_vs_1 = False
|
||||||
|
player.in_game = False
|
||||||
|
elif player.playervs2:
|
||||||
|
player.playervs2 = False
|
||||||
|
self._players_vs_2 = False
|
||||||
|
player.in_game = False
|
||||||
|
if player in self.spawn_order:
|
||||||
|
self.spawn_order.remove(player)
|
||||||
|
bs.timer(0.2, self._update_order)
|
||||||
|
|
||||||
|
def on_transition_in(self) -> None:
|
||||||
|
super().on_transition_in()
|
||||||
|
if self._night_mode:
|
||||||
|
gnode = bs.getactivity().globalsnode
|
||||||
|
gnode.tint = (0.3, 0.3, 0.3)
|
||||||
|
|
||||||
|
def on_team_join(self, team: Team) -> None:
|
||||||
|
if self.has_begun():
|
||||||
|
self._update_scoreboard()
|
||||||
|
|
||||||
|
def on_begin(self) -> None:
|
||||||
|
super().on_begin()
|
||||||
|
self.setup_standard_time_limit(self._time_limit)
|
||||||
|
if self._enable_powerups:
|
||||||
|
self.setup_standard_powerup_drops()
|
||||||
|
self._vs_text = bs.NodeActor(
|
||||||
|
bs.newnode('text',
|
||||||
|
attrs={
|
||||||
|
'position': (0, 105),
|
||||||
|
'h_attach': 'center',
|
||||||
|
'h_align': 'center',
|
||||||
|
'maxwidth': 200,
|
||||||
|
'shadow': 0.5,
|
||||||
|
'vr_depth': 390,
|
||||||
|
'scale': 0.6,
|
||||||
|
'v_attach': 'bottom',
|
||||||
|
'color': (0.8, 0.8, 0.3, 1.0),
|
||||||
|
'text': babase.Lstr(resource='vsText')
|
||||||
|
}))
|
||||||
|
|
||||||
|
# Base kills needed to win on the size of the largest team.
|
||||||
|
self._score_to_win = (self._kills_to_win_per_player *
|
||||||
|
max(1, max(len(t.players) for t in self.teams)))
|
||||||
|
self._update_scoreboard()
|
||||||
|
bs.timer(1.0, self._update, repeat=True)
|
||||||
|
|
||||||
|
def _update(self) -> None:
|
||||||
|
if len(self.players) == 1:
|
||||||
|
'self.end_game()'
|
||||||
|
|
||||||
|
def spawn_player(self, player: PlayerType) -> bs.Actor:
|
||||||
|
# pylint: disable=too-many-locals
|
||||||
|
# pylint: disable=cyclic-import
|
||||||
|
from babase import _math
|
||||||
|
from bascenev1._coopsession import CoopSession
|
||||||
|
from bascenev1lib.actor.spazfactory import SpazFactory
|
||||||
|
factory = SpazFactory.get()
|
||||||
|
name = player.getname()
|
||||||
|
color = player.color
|
||||||
|
highlight = player.highlight
|
||||||
|
|
||||||
|
light_color = _math.normalized_color(color)
|
||||||
|
display_color = babase.safecolor(color, target_intensity=0.75)
|
||||||
|
spaz = SuperSpaz(color=color,
|
||||||
|
highlight=highlight,
|
||||||
|
character=player.character,
|
||||||
|
player=player,
|
||||||
|
super_punch=True if self._super_punch else False)
|
||||||
|
|
||||||
|
player.actor = spaz
|
||||||
|
assert spaz.node
|
||||||
|
|
||||||
|
# If this is co-op and we're on Courtyard or Runaround, add the
|
||||||
|
# material that allows us to collide with the player-walls.
|
||||||
|
# FIXME: Need to generalize this.
|
||||||
|
if isinstance(self.session, CoopSession) and self.map.getname() in [
|
||||||
|
'Courtyard', 'Tower D'
|
||||||
|
]:
|
||||||
|
mat = self.map.preloaddata['collide_with_wall_material']
|
||||||
|
assert isinstance(spaz.node.materials, tuple)
|
||||||
|
assert isinstance(spaz.node.roller_materials, tuple)
|
||||||
|
spaz.node.materials += (mat, )
|
||||||
|
spaz.node.roller_materials += (mat, )
|
||||||
|
|
||||||
|
spaz.node.name = name
|
||||||
|
spaz.node.name_color = display_color
|
||||||
|
spaz.connect_controls_to_player()
|
||||||
|
|
||||||
|
self._spawn_sound.play(1, position=spaz.node.position)
|
||||||
|
light = bs.newnode('light', attrs={'color': light_color})
|
||||||
|
spaz.node.connectattr('position', light, 'position')
|
||||||
|
bs.animate(light, 'intensity', {0: 0, 0.25: 1, 0.5: 0})
|
||||||
|
bs.timer(0.5, light.delete)
|
||||||
|
|
||||||
|
pos1 = [self.map.get_start_position(0), 90]
|
||||||
|
pos2 = [self.map.get_start_position(1), 270]
|
||||||
|
pos3 = []
|
||||||
|
|
||||||
|
for x in self.players:
|
||||||
|
if x.is_alive():
|
||||||
|
if x is player:
|
||||||
|
continue
|
||||||
|
p = x.actor.node.position
|
||||||
|
if 0.0 not in (p[0], p[2]):
|
||||||
|
if p[0] <= 0:
|
||||||
|
pos3.append(pos2[0])
|
||||||
|
else:
|
||||||
|
pos3.append(pos1[0])
|
||||||
|
|
||||||
|
spaz.handlemessage(bs.StandMessage(pos1[0] if player.playervs1 else pos2[0],
|
||||||
|
pos1[1] if player.playervs1 else pos2[1]))
|
||||||
|
|
||||||
|
if any(pos3):
|
||||||
|
spaz.handlemessage(bs.StandMessage(pos3[0]))
|
||||||
|
|
||||||
|
if self._super_punch:
|
||||||
|
spaz._punch_power_scale = factory.punch_power_scale_gloves = 10
|
||||||
|
spaz.equip_boxing_gloves()
|
||||||
|
lfx = bs.newnode(
|
||||||
|
'light',
|
||||||
|
attrs={
|
||||||
|
'color': color,
|
||||||
|
'radius': 0.3,
|
||||||
|
'intensity': 0.3})
|
||||||
|
|
||||||
|
def sp_fx():
|
||||||
|
if not spaz.node:
|
||||||
|
lfx.delete()
|
||||||
|
return
|
||||||
|
bs.emitfx(position=spaz.node.position,
|
||||||
|
velocity=spaz.node.velocity,
|
||||||
|
count=5,
|
||||||
|
scale=0.5,
|
||||||
|
spread=0.5,
|
||||||
|
chunk_type='spark')
|
||||||
|
bs.emitfx(position=spaz.node.position,
|
||||||
|
velocity=spaz.node.velocity,
|
||||||
|
count=2,
|
||||||
|
scale=0.8,
|
||||||
|
spread=0.3,
|
||||||
|
chunk_type='spark')
|
||||||
|
if lfx:
|
||||||
|
spaz.node.connectattr('position', lfx, 'position')
|
||||||
|
bs.timer(0.1, sp_fx, repeat=True)
|
||||||
|
|
||||||
|
if self._box_mode:
|
||||||
|
spaz.node.color_texture = bs.gettexture('tnt')
|
||||||
|
spaz.node.color_mask_texture = bs.gettexture('tnt')
|
||||||
|
spaz.node.color = (1, 1, 1)
|
||||||
|
spaz.node.highlight = (1, 1, 1)
|
||||||
|
spaz.node.head_mesh = None
|
||||||
|
spaz.node.torso_mesh = bs.getmesh('tnt')
|
||||||
|
spaz.node.style = 'cyborg'
|
||||||
|
|
||||||
|
if self._boxing_gloves:
|
||||||
|
spaz.equip_boxing_gloves()
|
||||||
|
|
||||||
|
return spaz
|
||||||
|
|
||||||
|
def _update_spawn(self) -> None:
|
||||||
|
if self._players_vs_1 or self._players_vs_2:
|
||||||
|
for player in self.players:
|
||||||
|
if player.playervs1 or player.playervs2:
|
||||||
|
if not player.is_alive():
|
||||||
|
self.spawn_player(player)
|
||||||
|
# player.actor.disconnect_controls_from_player()
|
||||||
|
|
||||||
|
if self._night_mode:
|
||||||
|
if not player.light:
|
||||||
|
player.light = True
|
||||||
|
light = bs.newnode(
|
||||||
|
'light',
|
||||||
|
owner=player.node,
|
||||||
|
attrs={
|
||||||
|
'radius': 0.3,
|
||||||
|
'intensity': 0.6,
|
||||||
|
'height_attenuated': False,
|
||||||
|
'color': player.color
|
||||||
|
})
|
||||||
|
player.node.connectattr(
|
||||||
|
'position', light, 'position')
|
||||||
|
else:
|
||||||
|
player.actor.disconnect_controls_from_player()
|
||||||
|
|
||||||
|
bs.timer(0.0, self._countdown)
|
||||||
|
# bs.timer(0.1, self._clear_all_objects)
|
||||||
|
|
||||||
|
def _countdown(self) -> None:
|
||||||
|
self._first_countdown = False
|
||||||
|
if self._fight_delay == 0:
|
||||||
|
for player in self.players:
|
||||||
|
if player.playervs1 or player.playervs2:
|
||||||
|
if not player.is_alive():
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
player.actor.connect_controls_to_player()
|
||||||
|
else:
|
||||||
|
bs.timer(self._fight_delay, self.count3)
|
||||||
|
|
||||||
|
def start(self) -> None:
|
||||||
|
self._count_text('FIGHT')
|
||||||
|
self._boxing_bell.play()
|
||||||
|
for player in self.players:
|
||||||
|
if player.playervs1 or player.playervs2:
|
||||||
|
if not player.is_alive():
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
player.actor.connect_controls_to_player()
|
||||||
|
|
||||||
|
def count(self) -> None:
|
||||||
|
self._count_text('1')
|
||||||
|
self._count_1.play()
|
||||||
|
bs.timer(self._fight_delay, self.start)
|
||||||
|
|
||||||
|
def count2(self) -> None:
|
||||||
|
self._count_text('2')
|
||||||
|
self._count_2.play()
|
||||||
|
bs.timer(self._fight_delay, self.count)
|
||||||
|
|
||||||
|
def count3(self) -> None:
|
||||||
|
self._count_text('3')
|
||||||
|
self._count_3.play()
|
||||||
|
bs.timer(self._fight_delay, self.count2)
|
||||||
|
|
||||||
|
def _count_text(self, num: str) -> None:
|
||||||
|
self.node = bs.newnode('text',
|
||||||
|
attrs={
|
||||||
|
'v_attach': 'center',
|
||||||
|
'h_attach': 'center',
|
||||||
|
'h_align': 'center',
|
||||||
|
'color': (1, 1, 0.5, 1),
|
||||||
|
'flatness': 0.5,
|
||||||
|
'shadow': 0.5,
|
||||||
|
'position': (0, 18),
|
||||||
|
'text': num
|
||||||
|
})
|
||||||
|
if self._fight_delay == 0.7:
|
||||||
|
bs.animate(self.node, 'scale',
|
||||||
|
{0: 0, 0.1: 3.9, 0.64: 4.3, 0.68: 0})
|
||||||
|
elif self._fight_delay == 0.4:
|
||||||
|
bs.animate(self.node, 'scale',
|
||||||
|
{0: 0, 0.1: 3.9, 0.34: 4.3, 0.38: 0})
|
||||||
|
else:
|
||||||
|
bs.animate(self.node, 'scale',
|
||||||
|
{0: 0, 0.1: 3.9, 0.92: 4.3, 0.96: 0})
|
||||||
|
cmb = bs.newnode('combine', owner=self.node, attrs={'size': 4})
|
||||||
|
cmb.connectattr('output', self.node, 'color')
|
||||||
|
bs.animate(cmb, 'input0', {0: 1.0, 0.15: 1.0}, loop=True)
|
||||||
|
bs.animate(cmb, 'input1', {0: 1.0, 0.15: 0.5}, loop=True)
|
||||||
|
bs.animate(cmb, 'input2', {0: 0.1, 0.15: 0.0}, loop=True)
|
||||||
|
cmb.input3 = 1.0
|
||||||
|
bs.timer(self._fight_delay, self.node.delete)
|
||||||
|
|
||||||
|
def _update_order(self) -> None:
|
||||||
|
for player in self.spawn_order:
|
||||||
|
assert isinstance(player, Player)
|
||||||
|
if not player.is_alive():
|
||||||
|
if not self._players_vs_1:
|
||||||
|
self._players_vs_1 = True
|
||||||
|
player.playervs1 = True
|
||||||
|
player.in_game = True
|
||||||
|
self.spawn_order.remove(player)
|
||||||
|
self._update_spawn()
|
||||||
|
elif not self._players_vs_2:
|
||||||
|
self._players_vs_2 = True
|
||||||
|
player.playervs2 = True
|
||||||
|
player.in_game = True
|
||||||
|
self.spawn_order.remove(player)
|
||||||
|
self._update_spawn()
|
||||||
|
self._update_icons()
|
||||||
|
|
||||||
|
def _update_icons(self) -> None:
|
||||||
|
# pylint: disable=too-many-branches
|
||||||
|
|
||||||
|
for player in self.players:
|
||||||
|
player.icons = []
|
||||||
|
|
||||||
|
if player.in_game:
|
||||||
|
if player.playervs1:
|
||||||
|
xval = -60
|
||||||
|
x_offs = -78
|
||||||
|
elif player.playervs2:
|
||||||
|
xval = 60
|
||||||
|
x_offs = 78
|
||||||
|
player.icons.append(
|
||||||
|
Icon(player,
|
||||||
|
position=(xval, 40),
|
||||||
|
scale=1.0,
|
||||||
|
name_maxwidth=130,
|
||||||
|
name_scale=0.8,
|
||||||
|
flatness=0.0,
|
||||||
|
shadow=0.5,
|
||||||
|
show_death=True,
|
||||||
|
show_lives=False))
|
||||||
|
else:
|
||||||
|
xval = 125
|
||||||
|
xval2 = -125
|
||||||
|
x_offs = 78
|
||||||
|
for player in self.spawn_order:
|
||||||
|
player.icons.append(
|
||||||
|
Icon(player,
|
||||||
|
position=(xval, 25),
|
||||||
|
scale=0.5,
|
||||||
|
name_maxwidth=75,
|
||||||
|
name_scale=1.0,
|
||||||
|
flatness=1.0,
|
||||||
|
shadow=1.0,
|
||||||
|
show_death=False,
|
||||||
|
show_lives=False))
|
||||||
|
xval += x_offs * 0.56
|
||||||
|
player.icons.append(
|
||||||
|
Icon(player,
|
||||||
|
position=(xval2, 25),
|
||||||
|
scale=0.5,
|
||||||
|
name_maxwidth=75,
|
||||||
|
name_scale=1.0,
|
||||||
|
flatness=1.0,
|
||||||
|
shadow=1.0,
|
||||||
|
show_death=False,
|
||||||
|
show_lives=False))
|
||||||
|
xval2 -= x_offs * 0.56
|
||||||
|
|
||||||
|
def handlemessage(self, msg: Any) -> Any:
|
||||||
|
|
||||||
|
if isinstance(msg, bs.PlayerDiedMessage):
|
||||||
|
|
||||||
|
# Augment standard behavior.
|
||||||
|
super().handlemessage(msg)
|
||||||
|
|
||||||
|
player = msg.getplayer(Player)
|
||||||
|
|
||||||
|
if player.playervs1:
|
||||||
|
player.playervs1 = False
|
||||||
|
self._players_vs_1 = False
|
||||||
|
player.in_game = False
|
||||||
|
self.spawn_order.append(player)
|
||||||
|
elif player.playervs2:
|
||||||
|
player.playervs2 = False
|
||||||
|
self._players_vs_2 = False
|
||||||
|
player.in_game = False
|
||||||
|
self.spawn_order.append(player)
|
||||||
|
bs.timer(0.2, self._update_order)
|
||||||
|
|
||||||
|
killer = msg.getkillerplayer(Player)
|
||||||
|
if killer is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Handle team-kills.
|
||||||
|
if killer.team is player.team:
|
||||||
|
|
||||||
|
# In free-for-all, killing yourself loses you a point.
|
||||||
|
if isinstance(self.session, bs.FreeForAllSession):
|
||||||
|
new_score = player.team.score - 1
|
||||||
|
if not self._allow_negative_scores:
|
||||||
|
new_score = max(0, new_score)
|
||||||
|
player.team.score = new_score
|
||||||
|
|
||||||
|
# In teams-mode it gives a point to the other team.
|
||||||
|
else:
|
||||||
|
self._dingsound.play()
|
||||||
|
for team in self.teams:
|
||||||
|
if team is not killer.team:
|
||||||
|
team.score += 1
|
||||||
|
|
||||||
|
# Killing someone on another team nets a kill.
|
||||||
|
else:
|
||||||
|
killer.team.score += 1
|
||||||
|
self._dingsound.play()
|
||||||
|
|
||||||
|
# In FFA show scores since its hard to find on the scoreboard.
|
||||||
|
if isinstance(killer.actor, PlayerSpaz) and killer.actor:
|
||||||
|
killer.actor.set_score_text(str(killer.team.score) + '/' +
|
||||||
|
str(self._score_to_win),
|
||||||
|
color=killer.team.color,
|
||||||
|
flash=True)
|
||||||
|
|
||||||
|
self._update_scoreboard()
|
||||||
|
|
||||||
|
# If someone has won, set a timer to end shortly.
|
||||||
|
# (allows the dust to clear and draws to occur if deaths are
|
||||||
|
# close enough)
|
||||||
|
assert self._score_to_win is not None
|
||||||
|
if any(team.score >= self._score_to_win for team in self.teams):
|
||||||
|
bs.timer(0.5, self.end_game)
|
||||||
|
else:
|
||||||
|
return super().handlemessage(msg)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _update_scoreboard(self) -> None:
|
||||||
|
for team in self.teams:
|
||||||
|
self._scoreboard.set_team_value(team, team.score,
|
||||||
|
self._score_to_win)
|
||||||
|
|
||||||
|
def end_game(self) -> None:
|
||||||
|
results = bs.GameResults()
|
||||||
|
for team in self.teams:
|
||||||
|
results.set_team_score(team, team.score)
|
||||||
|
self.end(results=results)
|
||||||
956
plugins/minigames/supersmash.py
Normal file
956
plugins/minigames/supersmash.py
Normal file
|
|
@ -0,0 +1,956 @@
|
||||||
|
# To learn more, see https://ballistica.net/wiki/meta-tag-system
|
||||||
|
# ba_meta require api 8
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
import babase
|
||||||
|
import random
|
||||||
|
import bauiv1 as bui
|
||||||
|
import bascenev1 as bs
|
||||||
|
from babase import _math
|
||||||
|
from bascenev1lib.actor.spaz import Spaz
|
||||||
|
from bascenev1lib.actor.spazfactory import SpazFactory
|
||||||
|
from bascenev1lib.actor.scoreboard import Scoreboard
|
||||||
|
from bascenev1lib.game import elimination
|
||||||
|
from bascenev1lib.game.elimination import Icon, Player, Team
|
||||||
|
from bascenev1lib.actor.bomb import Bomb, Blast
|
||||||
|
from bascenev1lib.actor.playerspaz import PlayerSpaz, PlayerSpazHurtMessage
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from typing import Any, Type, List, Sequence, Optional
|
||||||
|
|
||||||
|
|
||||||
|
class Icon(Icon):
|
||||||
|
def update_for_lives(self) -> None:
|
||||||
|
"""Update for the target player's current lives."""
|
||||||
|
if self._player:
|
||||||
|
lives = self._player.lives
|
||||||
|
else:
|
||||||
|
lives = 0
|
||||||
|
if self._show_lives:
|
||||||
|
if lives > 1:
|
||||||
|
self._lives_text.text = 'x' + str(lives - 1)
|
||||||
|
else:
|
||||||
|
self._lives_text.text = ''
|
||||||
|
if lives == 0:
|
||||||
|
self._name_text.opacity = 0.2
|
||||||
|
assert self.node
|
||||||
|
self.node.color = (0.7, 0.3, 0.3)
|
||||||
|
self.node.opacity = 0.2
|
||||||
|
|
||||||
|
|
||||||
|
class PowBox(Bomb):
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
position: Sequence[float] = (0.0, 1.0, 0.0),
|
||||||
|
velocity: Sequence[float] = (0.0, 0.0, 0.0)) -> None:
|
||||||
|
Bomb.__init__(self,
|
||||||
|
position,
|
||||||
|
velocity,
|
||||||
|
bomb_type='tnt',
|
||||||
|
blast_radius=2.5,
|
||||||
|
source_player=None,
|
||||||
|
owner=None)
|
||||||
|
self.set_pow_text()
|
||||||
|
|
||||||
|
def set_pow_text(self) -> None:
|
||||||
|
m = bs.newnode('math',
|
||||||
|
owner=self.node,
|
||||||
|
attrs={'input1': (0, 0.7, 0),
|
||||||
|
'operation': 'add'})
|
||||||
|
self.node.connectattr('position', m, 'input2')
|
||||||
|
|
||||||
|
self._pow_text = bs.newnode('text',
|
||||||
|
owner=self.node,
|
||||||
|
attrs={'text': 'POW!',
|
||||||
|
'in_world': True,
|
||||||
|
'shadow': 1.0,
|
||||||
|
'flatness': 1.0,
|
||||||
|
'color': (1, 1, 0.4),
|
||||||
|
'scale': 0.0,
|
||||||
|
'h_align': 'center'})
|
||||||
|
m.connectattr('output', self._pow_text, 'position')
|
||||||
|
bs.animate(self._pow_text, 'scale', {0: 0.0, 1.0: 0.01})
|
||||||
|
|
||||||
|
def pow(self) -> None:
|
||||||
|
self.explode()
|
||||||
|
|
||||||
|
def handlemessage(self, m: Any) -> Any:
|
||||||
|
if isinstance(m, babase.PickedUpMessage):
|
||||||
|
self._heldBy = m.node
|
||||||
|
elif isinstance(m, bs.DroppedMessage):
|
||||||
|
bs.timer(0.6, self.pow)
|
||||||
|
Bomb.handlemessage(self, m)
|
||||||
|
|
||||||
|
|
||||||
|
class SSPlayerSpaz(PlayerSpaz):
|
||||||
|
multiplyer = 1
|
||||||
|
is_dead = False
|
||||||
|
|
||||||
|
def oob_effect(self) -> None:
|
||||||
|
if self.is_dead:
|
||||||
|
return
|
||||||
|
self.is_dead = True
|
||||||
|
if self.multiplyer > 1.25:
|
||||||
|
blast_type = 'tnt'
|
||||||
|
radius = min(self.multiplyer * 5, 20)
|
||||||
|
else:
|
||||||
|
# penalty for killing people with low multiplyer
|
||||||
|
blast_type = 'ice'
|
||||||
|
radius = 7.5
|
||||||
|
Blast(position=self.node.position,
|
||||||
|
blast_radius=radius,
|
||||||
|
blast_type=blast_type).autoretain()
|
||||||
|
|
||||||
|
def handlemessage(self, msg: Any) -> Any:
|
||||||
|
if isinstance(msg, bs.HitMessage):
|
||||||
|
if not self.node:
|
||||||
|
return None
|
||||||
|
if self.node.invincible:
|
||||||
|
SpazFactory.get().block_sound.play(1.0, position=self.node.position)
|
||||||
|
return True
|
||||||
|
|
||||||
|
# If we were recently hit, don't count this as another.
|
||||||
|
# (so punch flurries and bomb pileups essentially count as 1 hit)
|
||||||
|
local_time = int(bs.time() * 1000)
|
||||||
|
assert isinstance(local_time, int)
|
||||||
|
if (self._last_hit_time is None
|
||||||
|
or local_time - self._last_hit_time > 1000):
|
||||||
|
self._num_times_hit += 1
|
||||||
|
self._last_hit_time = local_time
|
||||||
|
|
||||||
|
mag = msg.magnitude * self.impact_scale
|
||||||
|
velocity_mag = msg.velocity_magnitude * self.impact_scale
|
||||||
|
damage_scale = 0.22
|
||||||
|
|
||||||
|
# If they've got a shield, deliver it to that instead.
|
||||||
|
if self.shield:
|
||||||
|
if msg.flat_damage:
|
||||||
|
damage = msg.flat_damage * self.impact_scale
|
||||||
|
else:
|
||||||
|
# Hit our spaz with an impulse but tell it to only return
|
||||||
|
# theoretical damage; not apply the impulse.
|
||||||
|
assert msg.force_direction is not None
|
||||||
|
self.node.handlemessage(
|
||||||
|
'impulse', msg.pos[0], msg.pos[1], msg.pos[2],
|
||||||
|
msg.velocity[0], msg.velocity[1], msg.velocity[2], mag,
|
||||||
|
velocity_mag, msg.radius, 1, msg.force_direction[0],
|
||||||
|
msg.force_direction[1], msg.force_direction[2])
|
||||||
|
damage = damage_scale * self.node.damage
|
||||||
|
|
||||||
|
assert self.shield_hitpoints is not None
|
||||||
|
self.shield_hitpoints -= int(damage)
|
||||||
|
self.shield.hurt = (
|
||||||
|
1.0 -
|
||||||
|
float(self.shield_hitpoints) / self.shield_hitpoints_max)
|
||||||
|
|
||||||
|
# Its a cleaner event if a hit just kills the shield
|
||||||
|
# without damaging the player.
|
||||||
|
# However, massive damage events should still be able to
|
||||||
|
# damage the player. This hopefully gives us a happy medium.
|
||||||
|
max_spillover = SpazFactory.get().max_shield_spillover_damage
|
||||||
|
if self.shield_hitpoints <= 0:
|
||||||
|
|
||||||
|
# FIXME: Transition out perhaps?
|
||||||
|
self.shield.delete()
|
||||||
|
self.shield = None
|
||||||
|
SpazFactory.get().shield_down_sound.play(1.0, position=self.node.position)
|
||||||
|
|
||||||
|
# Emit some cool looking sparks when the shield dies.
|
||||||
|
npos = self.node.position
|
||||||
|
bs.emitfx(position=(npos[0], npos[1] + 0.9, npos[2]),
|
||||||
|
velocity=self.node.velocity,
|
||||||
|
count=random.randrange(20, 30),
|
||||||
|
scale=1.0,
|
||||||
|
spread=0.6,
|
||||||
|
chunk_type='spark')
|
||||||
|
|
||||||
|
else:
|
||||||
|
SpazFactory.get().shield_hit_sound.play(0.5, position=self.node.position)
|
||||||
|
|
||||||
|
# Emit some cool looking sparks on shield hit.
|
||||||
|
assert msg.force_direction is not None
|
||||||
|
bs.emitfx(position=msg.pos,
|
||||||
|
velocity=(msg.force_direction[0] * 1.0,
|
||||||
|
msg.force_direction[1] * 1.0,
|
||||||
|
msg.force_direction[2] * 1.0),
|
||||||
|
count=min(30, 5 + int(damage * 0.005)),
|
||||||
|
scale=0.5,
|
||||||
|
spread=0.3,
|
||||||
|
chunk_type='spark')
|
||||||
|
|
||||||
|
# If they passed our spillover threshold,
|
||||||
|
# pass damage along to spaz.
|
||||||
|
if self.shield_hitpoints <= -max_spillover:
|
||||||
|
leftover_damage = -max_spillover - self.shield_hitpoints
|
||||||
|
shield_leftover_ratio = leftover_damage / damage
|
||||||
|
|
||||||
|
# Scale down the magnitudes applied to spaz accordingly.
|
||||||
|
mag *= shield_leftover_ratio
|
||||||
|
velocity_mag *= shield_leftover_ratio
|
||||||
|
else:
|
||||||
|
return True # Good job shield!
|
||||||
|
else:
|
||||||
|
shield_leftover_ratio = 1.0
|
||||||
|
|
||||||
|
if msg.flat_damage:
|
||||||
|
damage = int(msg.flat_damage * self.impact_scale *
|
||||||
|
shield_leftover_ratio)
|
||||||
|
else:
|
||||||
|
# Hit it with an impulse and get the resulting damage.
|
||||||
|
assert msg.force_direction is not None
|
||||||
|
self.node.handlemessage(
|
||||||
|
'impulse', msg.pos[0], msg.pos[1], msg.pos[2],
|
||||||
|
msg.velocity[0], msg.velocity[1], msg.velocity[2], mag,
|
||||||
|
velocity_mag, msg.radius, 0, msg.force_direction[0],
|
||||||
|
msg.force_direction[1], msg.force_direction[2])
|
||||||
|
|
||||||
|
damage = int(damage_scale * self.node.damage)
|
||||||
|
self.node.handlemessage('hurt_sound')
|
||||||
|
|
||||||
|
# Play punch impact sound based on damage if it was a punch.
|
||||||
|
if msg.hit_type == 'punch':
|
||||||
|
self.on_punched(damage)
|
||||||
|
|
||||||
|
# If damage was significant, lets show it.
|
||||||
|
# if damage > 350:
|
||||||
|
# assert msg.force_direction is not None
|
||||||
|
# babase.show_damage_count('-' + str(int(damage / 10)) + '%',
|
||||||
|
# msg.pos, msg.force_direction)
|
||||||
|
|
||||||
|
# Let's always add in a super-punch sound with boxing
|
||||||
|
# gloves just to differentiate them.
|
||||||
|
if msg.hit_subtype == 'super_punch':
|
||||||
|
SpazFactory.get().punch_sound_stronger.play(1.0, position=self.node.position)
|
||||||
|
if damage > 500:
|
||||||
|
sounds = SpazFactory.get().punch_sound_strong
|
||||||
|
sound = sounds[random.randrange(len(sounds))]
|
||||||
|
else:
|
||||||
|
sound = SpazFactory.get().punch_sound
|
||||||
|
sound.play(1.0, position=self.node.position)
|
||||||
|
|
||||||
|
# Throw up some chunks.
|
||||||
|
assert msg.force_direction is not None
|
||||||
|
bs.emitfx(position=msg.pos,
|
||||||
|
velocity=(msg.force_direction[0] * 0.5,
|
||||||
|
msg.force_direction[1] * 0.5,
|
||||||
|
msg.force_direction[2] * 0.5),
|
||||||
|
count=min(10, 1 + int(damage * 0.0025)),
|
||||||
|
scale=0.3,
|
||||||
|
spread=0.03)
|
||||||
|
|
||||||
|
bs.emitfx(position=msg.pos,
|
||||||
|
chunk_type='sweat',
|
||||||
|
velocity=(msg.force_direction[0] * 1.3,
|
||||||
|
msg.force_direction[1] * 1.3 + 5.0,
|
||||||
|
msg.force_direction[2] * 1.3),
|
||||||
|
count=min(30, 1 + int(damage * 0.04)),
|
||||||
|
scale=0.9,
|
||||||
|
spread=0.28)
|
||||||
|
|
||||||
|
# Momentary flash.
|
||||||
|
hurtiness = damage * 0.003
|
||||||
|
punchpos = (msg.pos[0] + msg.force_direction[0] * 0.02,
|
||||||
|
msg.pos[1] + msg.force_direction[1] * 0.02,
|
||||||
|
msg.pos[2] + msg.force_direction[2] * 0.02)
|
||||||
|
flash_color = (1.0, 0.8, 0.4)
|
||||||
|
light = bs.newnode(
|
||||||
|
'light',
|
||||||
|
attrs={
|
||||||
|
'position': punchpos,
|
||||||
|
'radius': 0.12 + hurtiness * 0.12,
|
||||||
|
'intensity': 0.3 * (1.0 + 1.0 * hurtiness),
|
||||||
|
'height_attenuated': False,
|
||||||
|
'color': flash_color
|
||||||
|
})
|
||||||
|
bs.timer(0.06, light.delete)
|
||||||
|
|
||||||
|
flash = bs.newnode('flash',
|
||||||
|
attrs={
|
||||||
|
'position': punchpos,
|
||||||
|
'size': 0.17 + 0.17 * hurtiness,
|
||||||
|
'color': flash_color
|
||||||
|
})
|
||||||
|
bs.timer(0.06, flash.delete)
|
||||||
|
|
||||||
|
if msg.hit_type == 'impact':
|
||||||
|
assert msg.force_direction is not None
|
||||||
|
bs.emitfx(position=msg.pos,
|
||||||
|
velocity=(msg.force_direction[0] * 2.0,
|
||||||
|
msg.force_direction[1] * 2.0,
|
||||||
|
msg.force_direction[2] * 2.0),
|
||||||
|
count=min(10, 1 + int(damage * 0.01)),
|
||||||
|
scale=0.4,
|
||||||
|
spread=0.1)
|
||||||
|
if self.hitpoints > 0:
|
||||||
|
|
||||||
|
# It's kinda crappy to die from impacts, so lets reduce
|
||||||
|
# impact damage by a reasonable amount *if* it'll keep us alive
|
||||||
|
if msg.hit_type == 'impact' and damage > self.hitpoints:
|
||||||
|
# Drop damage to whatever puts us at 10 hit points,
|
||||||
|
# or 200 less than it used to be whichever is greater
|
||||||
|
# (so it *can* still kill us if its high enough)
|
||||||
|
newdamage = max(damage - 200, self.hitpoints - 10)
|
||||||
|
damage = newdamage
|
||||||
|
self.node.handlemessage('flash')
|
||||||
|
|
||||||
|
# If we're holding something, drop it.
|
||||||
|
if damage > 0.0 and self.node.hold_node:
|
||||||
|
self.node.hold_node = None
|
||||||
|
# self.hitpoints -= damage
|
||||||
|
self.multiplyer += min(damage / 2000, 0.15)
|
||||||
|
if damage/2000 > 0.05:
|
||||||
|
self.set_score_text(str(int((self.multiplyer-1)*100))+'%')
|
||||||
|
# self.node.hurt = 1.0 - float(
|
||||||
|
# self.hitpoints) / self.hitpoints_max
|
||||||
|
self.node.hurt = 0.0
|
||||||
|
|
||||||
|
# If we're cursed, *any* damage blows us up.
|
||||||
|
if self._cursed and damage > 0:
|
||||||
|
bs.timer(
|
||||||
|
0.05,
|
||||||
|
bs.WeakCall(self.curse_explode,
|
||||||
|
msg.get_source_player(bs.Player)))
|
||||||
|
|
||||||
|
# If we're frozen, shatter.. otherwise die if we hit zero
|
||||||
|
# if self.frozen and (damage > 200 or self.hitpoints <= 0):
|
||||||
|
# self.shatter()
|
||||||
|
# elif self.hitpoints <= 0:
|
||||||
|
# self.node.handlemessage(
|
||||||
|
# bs.DieMessage(how=babase.DeathType.IMPACT))
|
||||||
|
|
||||||
|
# If we're dead, take a look at the smoothed damage value
|
||||||
|
# (which gives us a smoothed average of recent damage) and shatter
|
||||||
|
# us if its grown high enough.
|
||||||
|
# if self.hitpoints <= 0:
|
||||||
|
# damage_avg = self.node.damage_smoothed * damage_scale
|
||||||
|
# if damage_avg > 1000:
|
||||||
|
# self.shatter()
|
||||||
|
|
||||||
|
source_player = msg.get_source_player(type(self._player))
|
||||||
|
if source_player:
|
||||||
|
self.last_player_attacked_by = source_player
|
||||||
|
self.last_attacked_time = bs.time()
|
||||||
|
self.last_attacked_type = (msg.hit_type, msg.hit_subtype)
|
||||||
|
Spaz.handlemessage(self, bs.HitMessage) # Augment standard behavior.
|
||||||
|
activity = self._activity()
|
||||||
|
if activity is not None and self._player.exists():
|
||||||
|
activity.handlemessage(PlayerSpazHurtMessage(self))
|
||||||
|
|
||||||
|
elif isinstance(msg, bs.DieMessage):
|
||||||
|
self.oob_effect()
|
||||||
|
super().handlemessage(msg)
|
||||||
|
elif isinstance(msg, bs.PowerupMessage):
|
||||||
|
if msg.poweruptype == 'health':
|
||||||
|
if self.multiplyer > 2:
|
||||||
|
self.multiplyer *= 0.5
|
||||||
|
else:
|
||||||
|
self.multiplyer *= 0.75
|
||||||
|
self.multiplyer = max(1, self.multiplyer)
|
||||||
|
self.set_score_text(str(int((self.multiplyer-1)*100))+"%")
|
||||||
|
super().handlemessage(msg)
|
||||||
|
else:
|
||||||
|
super().handlemessage(msg)
|
||||||
|
|
||||||
|
|
||||||
|
class Player(bs.Player['Team']):
|
||||||
|
"""Our player type for this game."""
|
||||||
|
|
||||||
|
|
||||||
|
class Team(bs.Team[Player]):
|
||||||
|
"""Our team type for this game."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.score = 0
|
||||||
|
|
||||||
|
|
||||||
|
# ba_meta export bascenev1.GameActivity
|
||||||
|
class SuperSmash(bs.TeamGameActivity[Player, Team]):
|
||||||
|
|
||||||
|
name = 'Super Smash'
|
||||||
|
description = 'Knock everyone off the map.'
|
||||||
|
|
||||||
|
# Print messages when players die since it matters here.
|
||||||
|
announce_player_deaths = True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_available_settings(
|
||||||
|
cls, sessiontype: Type[bs.Session]) -> List[babase.Setting]:
|
||||||
|
settings = [
|
||||||
|
bs.IntSetting(
|
||||||
|
'Kills to Win Per Player',
|
||||||
|
min_value=1,
|
||||||
|
default=5,
|
||||||
|
increment=1,
|
||||||
|
),
|
||||||
|
bs.IntChoiceSetting(
|
||||||
|
'Time Limit',
|
||||||
|
choices=[
|
||||||
|
('None', 0),
|
||||||
|
('1 Minute', 60),
|
||||||
|
('2 Minutes', 120),
|
||||||
|
('5 Minutes', 300),
|
||||||
|
('10 Minutes', 600),
|
||||||
|
('20 Minutes', 1200),
|
||||||
|
],
|
||||||
|
default=0,
|
||||||
|
),
|
||||||
|
bs.FloatChoiceSetting(
|
||||||
|
'Respawn Times',
|
||||||
|
choices=[
|
||||||
|
('Shorter', 0.25),
|
||||||
|
('Short', 0.5),
|
||||||
|
('Normal', 1.0),
|
||||||
|
('Long', 2.0),
|
||||||
|
('Longer', 4.0),
|
||||||
|
],
|
||||||
|
default=1.0,
|
||||||
|
),
|
||||||
|
bs.BoolSetting('Boxing Gloves', default=False),
|
||||||
|
bs.BoolSetting('Epic Mode', default=False),
|
||||||
|
]
|
||||||
|
if issubclass(sessiontype, bs.FreeForAllSession):
|
||||||
|
settings.append(
|
||||||
|
bs.BoolSetting('Allow Negative Scores', default=False))
|
||||||
|
return settings
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def supports_session_type(cls, sessiontype: Type[bs.Session]) -> bool:
|
||||||
|
return (issubclass(sessiontype, bs.DualTeamSession)
|
||||||
|
or issubclass(sessiontype, bs.FreeForAllSession))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_supported_maps(cls, sessiontype: Type[bs.Session]) -> List[str]:
|
||||||
|
maps = bs.app.classic.getmaps('melee')
|
||||||
|
for m in ['Lake Frigid', 'Hockey Stadium', 'Football Stadium']:
|
||||||
|
# remove maps without bounds
|
||||||
|
maps.remove(m)
|
||||||
|
return maps
|
||||||
|
|
||||||
|
def __init__(self, settings: dict):
|
||||||
|
super().__init__(settings)
|
||||||
|
self._scoreboard = Scoreboard()
|
||||||
|
self._score_to_win: int | None = None
|
||||||
|
self._dingsound = bs.getsound('dingSmall')
|
||||||
|
self._epic_mode = bool(settings['Epic Mode'])
|
||||||
|
self._kills_to_win_per_player = int(
|
||||||
|
settings['Kills to Win Per Player'])
|
||||||
|
self._time_limit = float(settings['Time Limit'])
|
||||||
|
self._allow_negative_scores = bool(
|
||||||
|
settings.get('Allow Negative Scores', False))
|
||||||
|
self._boxing_gloves = bool(settings['Boxing Gloves'])
|
||||||
|
|
||||||
|
# Base class overrides.
|
||||||
|
self.slow_motion = self._epic_mode
|
||||||
|
self.default_music = (bs.MusicType.EPIC if self._epic_mode else
|
||||||
|
bs.MusicType.SURVIVAL)
|
||||||
|
|
||||||
|
def get_instance_description(self) -> str | Sequence:
|
||||||
|
return 'Knock everyone off the map.'
|
||||||
|
|
||||||
|
def get_instance_description_short(self) -> str | Sequence:
|
||||||
|
return 'Knock off the map.'
|
||||||
|
|
||||||
|
def on_begin(self) -> None:
|
||||||
|
super().on_begin()
|
||||||
|
self._start_time = bs.time()
|
||||||
|
self.setup_standard_time_limit(self._time_limit)
|
||||||
|
self.setup_standard_powerup_drops(enable_tnt=False)
|
||||||
|
self._pow = None
|
||||||
|
self._tnt_drop_timer = bs.timer(1.0 * 0.30,
|
||||||
|
bs.WeakCall(self._drop_pow_box),
|
||||||
|
repeat=True)
|
||||||
|
|
||||||
|
# Base kills needed to win on the size of the largest team.
|
||||||
|
self._score_to_win = (self._kills_to_win_per_player *
|
||||||
|
max(1, max(len(t.players) for t in self.teams)))
|
||||||
|
self._update_scoreboard()
|
||||||
|
|
||||||
|
def _drop_pow_box(self) -> None:
|
||||||
|
if self._pow is not None and self._pow:
|
||||||
|
return
|
||||||
|
if len(self.map.tnt_points) == 0:
|
||||||
|
return
|
||||||
|
pos = random.choice(self.map.tnt_points)
|
||||||
|
pos = (pos[0], pos[1] + 1, pos[2])
|
||||||
|
self._pow = PowBox(position=pos, velocity=(0.0, 1.0, 0.0))
|
||||||
|
|
||||||
|
def spawn_player(self, player: Player) -> bs.Actor:
|
||||||
|
if isinstance(self.session, bs.DualTeamSession):
|
||||||
|
position = self.map.get_start_position(player.team.id)
|
||||||
|
else:
|
||||||
|
# otherwise do free-for-all spawn locations
|
||||||
|
position = self.map.get_ffa_start_position(self.players)
|
||||||
|
angle = None
|
||||||
|
|
||||||
|
name = player.getname()
|
||||||
|
light_color = _math.normalized_color(player.color)
|
||||||
|
display_color = babase.safecolor(player.color, target_intensity=0.75)
|
||||||
|
|
||||||
|
spaz = SSPlayerSpaz(color=player.color,
|
||||||
|
highlight=player.highlight,
|
||||||
|
character=player.character,
|
||||||
|
player=player)
|
||||||
|
|
||||||
|
player.actor = spaz
|
||||||
|
assert spaz.node
|
||||||
|
|
||||||
|
# If this is co-op and we're on Courtyard or Runaround, add the
|
||||||
|
# material that allows us to collide with the player-walls.
|
||||||
|
# FIXME: Need to generalize this.
|
||||||
|
if isinstance(self.session, bs.CoopSession) and self.map.getname() in [
|
||||||
|
'Courtyard', 'Tower D'
|
||||||
|
]:
|
||||||
|
mat = self.map.preloaddata['collide_with_wall_material']
|
||||||
|
assert isinstance(spaz.node.materials, tuple)
|
||||||
|
assert isinstance(spaz.node.roller_materials, tuple)
|
||||||
|
spaz.node.materials += (mat, )
|
||||||
|
spaz.node.roller_materials += (mat, )
|
||||||
|
|
||||||
|
spaz.node.name = name
|
||||||
|
spaz.node.name_color = display_color
|
||||||
|
spaz.connect_controls_to_player()
|
||||||
|
|
||||||
|
# Move to the stand position and add a flash of light.
|
||||||
|
spaz.handlemessage(
|
||||||
|
bs.StandMessage(
|
||||||
|
position,
|
||||||
|
angle if angle is not None else random.uniform(0, 360)))
|
||||||
|
self._spawn_sound.play(1, position=spaz.node.position)
|
||||||
|
light = bs.newnode('light', attrs={'color': light_color})
|
||||||
|
spaz.node.connectattr('position', light, 'position')
|
||||||
|
bs.animate(light, 'intensity', {0: 0, 0.25: 1, 0.5: 0})
|
||||||
|
bs.timer(0.5, light.delete)
|
||||||
|
|
||||||
|
if self._boxing_gloves:
|
||||||
|
spaz.equip_boxing_gloves()
|
||||||
|
|
||||||
|
return spaz
|
||||||
|
|
||||||
|
def handlemessage(self, msg: Any) -> Any:
|
||||||
|
|
||||||
|
if isinstance(msg, bs.PlayerDiedMessage):
|
||||||
|
# Augment standard behavior.
|
||||||
|
super().handlemessage(msg)
|
||||||
|
|
||||||
|
player = msg.getplayer(Player)
|
||||||
|
self.respawn_player(player)
|
||||||
|
|
||||||
|
killer = msg.getkillerplayer(Player)
|
||||||
|
if killer is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Handle team-kills.
|
||||||
|
if killer.team is player.team:
|
||||||
|
|
||||||
|
# In free-for-all, killing yourself loses you a point.
|
||||||
|
if isinstance(self.session, bs.FreeForAllSession):
|
||||||
|
new_score = player.team.score - 1
|
||||||
|
if not self._allow_negative_scores:
|
||||||
|
new_score = max(0, new_score)
|
||||||
|
player.team.score = new_score
|
||||||
|
|
||||||
|
# In teams-mode it gives a point to the other team.
|
||||||
|
else:
|
||||||
|
self._dingsound.play()
|
||||||
|
for team in self.teams:
|
||||||
|
if team is not killer.team:
|
||||||
|
team.score += 1
|
||||||
|
|
||||||
|
# Killing someone on another team nets a kill.
|
||||||
|
else:
|
||||||
|
killer.team.score += 1
|
||||||
|
self._dingsound.play()
|
||||||
|
|
||||||
|
# In FFA show scores since its hard to find on the scoreboard.
|
||||||
|
if isinstance(killer.actor, SSPlayerSpaz) and killer.actor:
|
||||||
|
killer.actor.set_score_text(str(killer.team.score) + '/' +
|
||||||
|
str(self._score_to_win),
|
||||||
|
color=killer.team.color,
|
||||||
|
flash=True)
|
||||||
|
|
||||||
|
self._update_scoreboard()
|
||||||
|
|
||||||
|
# If someone has won, set a timer to end shortly.
|
||||||
|
# (allows the dust to clear and draws to occur if deaths are
|
||||||
|
# close enough)
|
||||||
|
assert self._score_to_win is not None
|
||||||
|
if any(team.score >= self._score_to_win for team in self.teams):
|
||||||
|
bs.timer(0.5, self.end_game)
|
||||||
|
|
||||||
|
else:
|
||||||
|
return super().handlemessage(msg)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _update_scoreboard(self) -> None:
|
||||||
|
for team in self.teams:
|
||||||
|
self._scoreboard.set_team_value(team, team.score,
|
||||||
|
self._score_to_win)
|
||||||
|
|
||||||
|
def end_game(self) -> None:
|
||||||
|
results = bs.GameResults()
|
||||||
|
for team in self.teams:
|
||||||
|
results.set_team_score(team, team.score)
|
||||||
|
self.end(results=results)
|
||||||
|
|
||||||
|
|
||||||
|
class Player2(bs.Player['Team']):
|
||||||
|
"""Our player type for this game."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.lives = 0
|
||||||
|
self.icons: List[Icon] = []
|
||||||
|
|
||||||
|
|
||||||
|
class Team2(bs.Team[Player]):
|
||||||
|
"""Our team type for this game."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.survival_seconds: Optional[int] = None
|
||||||
|
self.spawn_order: List[Player] = []
|
||||||
|
|
||||||
|
|
||||||
|
# ba_meta export bascenev1.GameActivity
|
||||||
|
class SuperSmashElimination(bs.TeamGameActivity[Player2, Team2]):
|
||||||
|
|
||||||
|
name = 'Super Smash Elimination'
|
||||||
|
description = 'Knock everyone off the map.'
|
||||||
|
scoreconfig = bs.ScoreConfig(label='Survived',
|
||||||
|
scoretype=bs.ScoreType.SECONDS,
|
||||||
|
none_is_winner=True)
|
||||||
|
|
||||||
|
# Print messages when players die since it matters here.
|
||||||
|
announce_player_deaths = True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_available_settings(
|
||||||
|
cls, sessiontype: Type[bs.Session]) -> List[babase.Setting]:
|
||||||
|
settings = [
|
||||||
|
bs.IntSetting(
|
||||||
|
'Lives (0 = Unlimited)',
|
||||||
|
min_value=0,
|
||||||
|
default=3,
|
||||||
|
increment=1,
|
||||||
|
),
|
||||||
|
bs.IntChoiceSetting(
|
||||||
|
'Time Limit',
|
||||||
|
choices=[
|
||||||
|
('None', 0),
|
||||||
|
('1 Minute', 60),
|
||||||
|
('2 Minutes', 120),
|
||||||
|
('5 Minutes', 300),
|
||||||
|
('10 Minutes', 600),
|
||||||
|
('20 Minutes', 1200),
|
||||||
|
],
|
||||||
|
default=0,
|
||||||
|
),
|
||||||
|
bs.FloatChoiceSetting(
|
||||||
|
'Respawn Times',
|
||||||
|
choices=[
|
||||||
|
('Shorter', 0.25),
|
||||||
|
('Short', 0.5),
|
||||||
|
('Normal', 1.0),
|
||||||
|
('Long', 2.0),
|
||||||
|
('Longer', 4.0),
|
||||||
|
],
|
||||||
|
default=1.0,
|
||||||
|
),
|
||||||
|
bs.BoolSetting('Boxing Gloves', default=False),
|
||||||
|
bs.BoolSetting('Epic Mode', default=False),
|
||||||
|
]
|
||||||
|
return settings
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def supports_session_type(cls, sessiontype: Type[bs.Session]) -> bool:
|
||||||
|
return (issubclass(sessiontype, bs.DualTeamSession)
|
||||||
|
or issubclass(sessiontype, bs.FreeForAllSession))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_supported_maps(cls, sessiontype: Type[bs.Session]) -> List[str]:
|
||||||
|
maps = bs.app.classic.getmaps('melee')
|
||||||
|
for m in ['Lake Frigid', 'Hockey Stadium', 'Football Stadium']:
|
||||||
|
# remove maps without bounds
|
||||||
|
maps.remove(m)
|
||||||
|
return maps
|
||||||
|
|
||||||
|
def __init__(self, settings: dict):
|
||||||
|
super().__init__(settings)
|
||||||
|
self.lives = int(settings['Lives (0 = Unlimited)'])
|
||||||
|
self.time_limit_only = (self.lives == 0)
|
||||||
|
if self.time_limit_only:
|
||||||
|
settings['Time Limit'] = max(60, settings['Time Limit'])
|
||||||
|
|
||||||
|
self._epic_mode = bool(settings['Epic Mode'])
|
||||||
|
self._time_limit = float(settings['Time Limit'])
|
||||||
|
|
||||||
|
self._start_time: Optional[float] = 1.0
|
||||||
|
|
||||||
|
self._boxing_gloves = bool(settings['Boxing Gloves'])
|
||||||
|
self._solo_mode = bool(settings.get('Solo Mode', False))
|
||||||
|
|
||||||
|
# Base class overrides.
|
||||||
|
self.slow_motion = self._epic_mode
|
||||||
|
self.default_music = (bs.MusicType.EPIC if self._epic_mode else
|
||||||
|
bs.MusicType.SURVIVAL)
|
||||||
|
|
||||||
|
def get_instance_description(self) -> str | Sequence:
|
||||||
|
return 'Knock everyone off the map.'
|
||||||
|
|
||||||
|
def get_instance_description_short(self) -> str | Sequence:
|
||||||
|
return 'Knock off the map.'
|
||||||
|
|
||||||
|
def on_begin(self) -> None:
|
||||||
|
super().on_begin()
|
||||||
|
self._start_time = bs.time()
|
||||||
|
self.setup_standard_time_limit(self._time_limit)
|
||||||
|
self.setup_standard_powerup_drops(enable_tnt=False)
|
||||||
|
self._pow = None
|
||||||
|
self._tnt_drop_timer = bs.timer(1.0 * 0.30,
|
||||||
|
bs.WeakCall(self._drop_pow_box),
|
||||||
|
repeat=True)
|
||||||
|
self._update_icons()
|
||||||
|
bs.timer(1.0, self.check_end_game, repeat=True)
|
||||||
|
|
||||||
|
def _drop_pow_box(self) -> None:
|
||||||
|
if self._pow is not None and self._pow:
|
||||||
|
return
|
||||||
|
if len(self.map.tnt_points) == 0:
|
||||||
|
return
|
||||||
|
pos = random.choice(self.map.tnt_points)
|
||||||
|
pos = (pos[0], pos[1] + 1, pos[2])
|
||||||
|
self._pow = PowBox(position=pos, velocity=(0.0, 1.0, 0.0))
|
||||||
|
|
||||||
|
def on_player_join(self, player: Player) -> None:
|
||||||
|
|
||||||
|
if self.has_begun():
|
||||||
|
if (all(teammate.lives == 0 for teammate in player.team.players)
|
||||||
|
and player.team.survival_seconds is None):
|
||||||
|
player.team.survival_seconds = 0
|
||||||
|
bs.broadcastmessage(
|
||||||
|
babase.Lstr(resource='playerDelayedJoinText',
|
||||||
|
subs=[('${PLAYER}', player.getname(full=True))]),
|
||||||
|
color=(0, 1, 0),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
player.lives = self.lives
|
||||||
|
# create our icon and spawn
|
||||||
|
player.icons = [Icon(player,
|
||||||
|
position=(0.0, 50),
|
||||||
|
scale=0.8)]
|
||||||
|
if player.lives > 0 or self.time_limit_only:
|
||||||
|
self.spawn_player(player)
|
||||||
|
|
||||||
|
# dont waste time doing this until begin
|
||||||
|
if self.has_begun():
|
||||||
|
self._update_icons()
|
||||||
|
|
||||||
|
def on_player_leave(self, player: Player) -> None:
|
||||||
|
super().on_player_leave(player)
|
||||||
|
player.icons = None
|
||||||
|
|
||||||
|
# update icons in a moment since our team
|
||||||
|
# will be gone from the list then
|
||||||
|
bs.timer(0.0, self._update_icons)
|
||||||
|
bs.timer(0.1, self.check_end_game, repeat=True)
|
||||||
|
|
||||||
|
def _update_icons(self) -> None:
|
||||||
|
# pylint: disable=too-many-branches
|
||||||
|
|
||||||
|
# In free-for-all mode, everyone is just lined up along the bottom.
|
||||||
|
if isinstance(self.session, bs.FreeForAllSession):
|
||||||
|
count = len(self.teams)
|
||||||
|
x_offs = 85
|
||||||
|
xval = x_offs * (count - 1) * -0.5
|
||||||
|
for team in self.teams:
|
||||||
|
if len(team.players) > 1:
|
||||||
|
print('WTF have', len(team.players), 'players in ffa team')
|
||||||
|
elif len(team.players) == 1:
|
||||||
|
player = team.players[0]
|
||||||
|
if len(player.icons) != 1:
|
||||||
|
print(
|
||||||
|
'WTF have',
|
||||||
|
len(player.icons),
|
||||||
|
'icons in non-solo elim')
|
||||||
|
for icon in player.icons:
|
||||||
|
icon.set_position_and_scale((xval, 30), 0.7)
|
||||||
|
icon.update_for_lives()
|
||||||
|
xval += x_offs
|
||||||
|
|
||||||
|
# In teams mode we split up teams.
|
||||||
|
else:
|
||||||
|
if self._solo_mode:
|
||||||
|
# First off, clear out all icons.
|
||||||
|
for player in self.players:
|
||||||
|
player.icons = []
|
||||||
|
|
||||||
|
# Now for each team, cycle through our available players
|
||||||
|
# adding icons.
|
||||||
|
for team in self.teams:
|
||||||
|
if team.id == 0:
|
||||||
|
xval = -60
|
||||||
|
x_offs = -78
|
||||||
|
else:
|
||||||
|
xval = 60
|
||||||
|
x_offs = 78
|
||||||
|
is_first = True
|
||||||
|
test_lives = 1
|
||||||
|
while True:
|
||||||
|
players_with_lives = [
|
||||||
|
p for p in team.spawn_order
|
||||||
|
if p and p.lives >= test_lives
|
||||||
|
]
|
||||||
|
if not players_with_lives:
|
||||||
|
break
|
||||||
|
for player in players_with_lives:
|
||||||
|
player.icons.append(
|
||||||
|
Icon(player,
|
||||||
|
position=(xval, (40 if is_first else 25)),
|
||||||
|
scale=1.0 if is_first else 0.5,
|
||||||
|
name_maxwidth=130 if is_first else 75,
|
||||||
|
name_scale=0.8 if is_first else 1.0,
|
||||||
|
flatness=0.0 if is_first else 1.0,
|
||||||
|
shadow=0.5 if is_first else 1.0,
|
||||||
|
show_death=is_first,
|
||||||
|
show_lives=False))
|
||||||
|
xval += x_offs * (0.8 if is_first else 0.56)
|
||||||
|
is_first = False
|
||||||
|
test_lives += 1
|
||||||
|
# Non-solo mode.
|
||||||
|
else:
|
||||||
|
for team in self.teams:
|
||||||
|
if team.id == 0:
|
||||||
|
xval = -50
|
||||||
|
x_offs = -85
|
||||||
|
else:
|
||||||
|
xval = 50
|
||||||
|
x_offs = 85
|
||||||
|
for player in team.players:
|
||||||
|
if len(player.icons) != 1:
|
||||||
|
print(
|
||||||
|
'WTF have',
|
||||||
|
len(player.icons),
|
||||||
|
'icons in non-solo elim')
|
||||||
|
for icon in player.icons:
|
||||||
|
icon.set_position_and_scale((xval, 30), 0.7)
|
||||||
|
icon.update_for_lives()
|
||||||
|
xval += x_offs
|
||||||
|
|
||||||
|
# overriding the default character spawning..
|
||||||
|
def spawn_player(self, player: Player) -> bs.Actor:
|
||||||
|
if isinstance(self.session, bs.DualTeamSession):
|
||||||
|
position = self.map.get_start_position(player.team.id)
|
||||||
|
else:
|
||||||
|
# otherwise do free-for-all spawn locations
|
||||||
|
position = self.map.get_ffa_start_position(self.players)
|
||||||
|
angle = None
|
||||||
|
|
||||||
|
name = player.getname()
|
||||||
|
light_color = _math.normalized_color(player.color)
|
||||||
|
display_color = babase.safecolor(player.color, target_intensity=0.75)
|
||||||
|
|
||||||
|
spaz = SSPlayerSpaz(color=player.color,
|
||||||
|
highlight=player.highlight,
|
||||||
|
character=player.character,
|
||||||
|
player=player)
|
||||||
|
|
||||||
|
player.actor = spaz
|
||||||
|
assert spaz.node
|
||||||
|
|
||||||
|
# If this is co-op and we're on Courtyard or Runaround, add the
|
||||||
|
# material that allows us to collide with the player-walls.
|
||||||
|
# FIXME: Need to generalize this.
|
||||||
|
if isinstance(self.session, bs.CoopSession) and self.map.getname() in [
|
||||||
|
'Courtyard', 'Tower D'
|
||||||
|
]:
|
||||||
|
mat = self.map.preloaddata['collide_with_wall_material']
|
||||||
|
assert isinstance(spaz.node.materials, tuple)
|
||||||
|
assert isinstance(spaz.node.roller_materials, tuple)
|
||||||
|
spaz.node.materials += (mat, )
|
||||||
|
spaz.node.roller_materials += (mat, )
|
||||||
|
|
||||||
|
spaz.node.name = name
|
||||||
|
spaz.node.name_color = display_color
|
||||||
|
spaz.connect_controls_to_player()
|
||||||
|
|
||||||
|
# Move to the stand position and add a flash of light.
|
||||||
|
spaz.handlemessage(
|
||||||
|
bs.StandMessage(
|
||||||
|
position,
|
||||||
|
angle if angle is not None else random.uniform(0, 360)))
|
||||||
|
self._spawn_sound.play(1, position=spaz.node.position)
|
||||||
|
light = bs.newnode('light', attrs={'color': light_color})
|
||||||
|
spaz.node.connectattr('position', light, 'position')
|
||||||
|
bs.animate(light, 'intensity', {0: 0, 0.25: 1, 0.5: 0})
|
||||||
|
bs.timer(0.5, light.delete)
|
||||||
|
|
||||||
|
# If we have any icons, update their state.
|
||||||
|
for icon in player.icons:
|
||||||
|
icon.handle_player_spawned()
|
||||||
|
|
||||||
|
if self._boxing_gloves:
|
||||||
|
spaz.equip_boxing_gloves()
|
||||||
|
|
||||||
|
return spaz
|
||||||
|
|
||||||
|
def _get_total_team_lives(self, team: Team) -> int:
|
||||||
|
return sum(player.lives for player in team.players)
|
||||||
|
|
||||||
|
def handlemessage(self, msg: Any) -> Any:
|
||||||
|
|
||||||
|
if isinstance(msg, bs.PlayerDiedMessage):
|
||||||
|
# Augment standard behavior.
|
||||||
|
super().handlemessage(msg)
|
||||||
|
player: Player = msg.getplayer(Player)
|
||||||
|
|
||||||
|
player.lives -= 1
|
||||||
|
if player.lives < 0:
|
||||||
|
player.lives = 0
|
||||||
|
|
||||||
|
# if we have any icons, update their state
|
||||||
|
for icon in player.icons:
|
||||||
|
icon.handle_player_died()
|
||||||
|
|
||||||
|
# play big death sound on our last death
|
||||||
|
# or for every one in solo mode
|
||||||
|
if player.lives == 0:
|
||||||
|
SpazFactory.get().single_player_death_sound.play()
|
||||||
|
|
||||||
|
# if we hit zero lives we're dead and the game might be over
|
||||||
|
if player.lives == 0 and not self.time_limit_only:
|
||||||
|
# If the whole team is now dead, mark their survival time.
|
||||||
|
if self._get_total_team_lives(player.team) == 0:
|
||||||
|
assert self._start_time is not None
|
||||||
|
player.team.survival_seconds = int(bs.time() -
|
||||||
|
self._start_time)
|
||||||
|
# we still have lives; yay!
|
||||||
|
else:
|
||||||
|
self.respawn_player(player)
|
||||||
|
|
||||||
|
bs.timer(0.1, self.check_end_game, repeat=True)
|
||||||
|
|
||||||
|
else:
|
||||||
|
return super().handlemessage(msg)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def check_end_game(self) -> None:
|
||||||
|
if len(self._get_living_teams()) < 2:
|
||||||
|
bs.timer(0.5, self.end_game)
|
||||||
|
|
||||||
|
def _get_living_teams(self) -> List[Team]:
|
||||||
|
return [
|
||||||
|
team for team in self.teams
|
||||||
|
if len(team.players) > 0 and any(player.lives > 0
|
||||||
|
for player in team.players)
|
||||||
|
]
|
||||||
|
|
||||||
|
def end_game(self) -> None:
|
||||||
|
if self.has_ended():
|
||||||
|
return
|
||||||
|
results = bs.GameResults()
|
||||||
|
self._vs_text = None # Kill our 'vs' if its there.
|
||||||
|
for team in self.teams:
|
||||||
|
results.set_team_score(team, team.survival_seconds)
|
||||||
|
self.end(results=results)
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Volley Ball (final)
|
# Volley Ball (final)
|
||||||
|
|
||||||
# Made by your friend: Freaku / @[Just] Freak#4999
|
# Made by your friend: Freaku
|
||||||
|
|
||||||
|
|
||||||
# Join BCS:
|
# Join BCS:
|
||||||
|
|
@ -28,25 +28,24 @@
|
||||||
|
|
||||||
## 2022
|
## 2022
|
||||||
- Code cleanup
|
- Code cleanup
|
||||||
- No longer requires a plugin
|
|
||||||
- More accurate Goal positions
|
- More accurate Goal positions
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
# ba_meta require api 7
|
# ba_meta require api 8
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import _ba
|
import babase
|
||||||
import ba
|
|
||||||
import random
|
import random
|
||||||
from bastd.actor.playerspaz import PlayerSpaz
|
import bascenev1 as bs
|
||||||
from bastd.actor.scoreboard import Scoreboard
|
from bascenev1lib.actor.playerspaz import PlayerSpaz
|
||||||
from bastd.actor.powerupbox import PowerupBoxFactory
|
from bascenev1lib.actor.scoreboard import Scoreboard
|
||||||
from bastd.actor.bomb import BombFactory
|
from bascenev1lib.actor.powerupbox import PowerupBoxFactory
|
||||||
from bastd.gameutils import SharedObjects
|
from bascenev1lib.actor.bomb import BombFactory
|
||||||
|
from bascenev1lib.gameutils import SharedObjects
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any, Sequence, Dict, Type, List, Optional, Union
|
from typing import Any, Sequence, Dict, Type, List, Optional, Union
|
||||||
|
|
@ -59,7 +58,7 @@ class PuckDiedMessage:
|
||||||
self.puck = puck
|
self.puck = puck
|
||||||
|
|
||||||
|
|
||||||
class Puck(ba.Actor):
|
class Puck(bs.Actor):
|
||||||
def __init__(self, position: Sequence[float] = (0.0, 1.0, 0.0)):
|
def __init__(self, position: Sequence[float] = (0.0, 1.0, 0.0)):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
shared = SharedObjects.get()
|
shared = SharedObjects.get()
|
||||||
|
|
@ -72,16 +71,16 @@ class Puck(ba.Actor):
|
||||||
assert activity is not None
|
assert activity is not None
|
||||||
assert isinstance(activity, VolleyBallGame)
|
assert isinstance(activity, VolleyBallGame)
|
||||||
pmats = [shared.object_material, activity.puck_material]
|
pmats = [shared.object_material, activity.puck_material]
|
||||||
self.node = ba.newnode('prop',
|
self.node = bs.newnode('prop',
|
||||||
delegate=self,
|
delegate=self,
|
||||||
attrs={
|
attrs={
|
||||||
'model': activity.puck_model,
|
'mesh': activity.puck_mesh,
|
||||||
'color_texture': activity.puck_tex,
|
'color_texture': activity.puck_tex,
|
||||||
'body': 'sphere',
|
'body': 'sphere',
|
||||||
'reflection': 'soft',
|
'reflection': 'soft',
|
||||||
'reflection_scale': [0.2],
|
'reflection_scale': [0.2],
|
||||||
'shadow_size': 0.6,
|
'shadow_size': 0.6,
|
||||||
'model_scale': 0.4,
|
'mesh_scale': 0.4,
|
||||||
'body_scale': 1.07,
|
'body_scale': 1.07,
|
||||||
'is_area_of_interest': True,
|
'is_area_of_interest': True,
|
||||||
'position': self._spawn_pos,
|
'position': self._spawn_pos,
|
||||||
|
|
@ -91,11 +90,11 @@ class Puck(ba.Actor):
|
||||||
# Since it rolls on spawn, lets make gravity
|
# Since it rolls on spawn, lets make gravity
|
||||||
# to 0, and when another node (bomb/spaz)
|
# to 0, and when another node (bomb/spaz)
|
||||||
# touches it. It'll act back as our normie puck!
|
# touches it. It'll act back as our normie puck!
|
||||||
ba.animate(self.node, 'gravity_scale', {0: -0.1, 0.2: 1}, False)
|
bs.animate(self.node, 'gravity_scale', {0: -0.1, 0.2: 1}, False)
|
||||||
# When other node touches, it realises its new gravity_scale
|
# When other node touches, it realises its new gravity_scale
|
||||||
|
|
||||||
def handlemessage(self, msg: Any) -> Any:
|
def handlemessage(self, msg: Any) -> Any:
|
||||||
if isinstance(msg, ba.DieMessage):
|
if isinstance(msg, bs.DieMessage):
|
||||||
assert self.node
|
assert self.node
|
||||||
self.node.delete()
|
self.node.delete()
|
||||||
activity = self._activity()
|
activity = self._activity()
|
||||||
|
|
@ -103,11 +102,11 @@ class Puck(ba.Actor):
|
||||||
activity.handlemessage(PuckDiedMessage(self))
|
activity.handlemessage(PuckDiedMessage(self))
|
||||||
|
|
||||||
# If we go out of bounds, move back to where we started.
|
# If we go out of bounds, move back to where we started.
|
||||||
elif isinstance(msg, ba.OutOfBoundsMessage):
|
elif isinstance(msg, bs.OutOfBoundsMessage):
|
||||||
assert self.node
|
assert self.node
|
||||||
self.node.position = self._spawn_pos
|
self.node.position = self._spawn_pos
|
||||||
|
|
||||||
elif isinstance(msg, ba.HitMessage):
|
elif isinstance(msg, bs.HitMessage):
|
||||||
assert self.node
|
assert self.node
|
||||||
assert msg.force_direction is not None
|
assert msg.force_direction is not None
|
||||||
self.node.handlemessage(
|
self.node.handlemessage(
|
||||||
|
|
@ -128,29 +127,29 @@ class Puck(ba.Actor):
|
||||||
super().handlemessage(msg)
|
super().handlemessage(msg)
|
||||||
|
|
||||||
|
|
||||||
class Player(ba.Player['Team']):
|
class Player(bs.Player['Team']):
|
||||||
"""Our player type for this game."""
|
"""Our player type for this game."""
|
||||||
|
|
||||||
|
|
||||||
class Team(ba.Team[Player]):
|
class Team(bs.Team[Player]):
|
||||||
"""Our team type for this game."""
|
"""Our team type for this game."""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.score = 0
|
self.score = 0
|
||||||
|
|
||||||
|
|
||||||
# ba_meta export game
|
# ba_meta export bascenev1.GameActivity
|
||||||
class VolleyBallGame(ba.TeamGameActivity[Player, Team]):
|
class VolleyBallGame(bs.TeamGameActivity[Player, Team]):
|
||||||
name = 'Volley Ball'
|
name = 'Volley Ball'
|
||||||
description = 'Score some goals.\nby \ue048Freaku'
|
description = 'Score some goals.\nby \ue048Freaku'
|
||||||
available_settings = [
|
available_settings = [
|
||||||
ba.IntSetting(
|
bs.IntSetting(
|
||||||
'Score to Win',
|
'Score to Win',
|
||||||
min_value=1,
|
min_value=1,
|
||||||
default=1,
|
default=1,
|
||||||
increment=1,
|
increment=1,
|
||||||
),
|
),
|
||||||
ba.IntChoiceSetting(
|
bs.IntChoiceSetting(
|
||||||
'Time Limit',
|
'Time Limit',
|
||||||
choices=[
|
choices=[
|
||||||
('None', 0),
|
('None', 0),
|
||||||
|
|
@ -162,7 +161,7 @@ class VolleyBallGame(ba.TeamGameActivity[Player, Team]):
|
||||||
],
|
],
|
||||||
default=0,
|
default=0,
|
||||||
),
|
),
|
||||||
ba.FloatChoiceSetting(
|
bs.FloatChoiceSetting(
|
||||||
'Respawn Times',
|
'Respawn Times',
|
||||||
choices=[
|
choices=[
|
||||||
('Shorter', 0.25),
|
('Shorter', 0.25),
|
||||||
|
|
@ -173,36 +172,36 @@ class VolleyBallGame(ba.TeamGameActivity[Player, Team]):
|
||||||
],
|
],
|
||||||
default=1.0,
|
default=1.0,
|
||||||
),
|
),
|
||||||
ba.BoolSetting('Epic Mode', True),
|
bs.BoolSetting('Epic Mode', True),
|
||||||
ba.BoolSetting('Night Mode', False),
|
bs.BoolSetting('Night Mode', False),
|
||||||
ba.BoolSetting('Icy Floor', True),
|
bs.BoolSetting('Icy Floor', True),
|
||||||
ba.BoolSetting('Disable Punch', False),
|
bs.BoolSetting('Disable Punch', False),
|
||||||
ba.BoolSetting('Disable Bombs', False),
|
bs.BoolSetting('Disable Bombs', False),
|
||||||
ba.BoolSetting('Enable Bottom Credits', True),
|
bs.BoolSetting('Enable Bottom Credits', True),
|
||||||
]
|
]
|
||||||
default_music = ba.MusicType.HOCKEY
|
default_music = bs.MusicType.HOCKEY
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
|
def supports_session_type(cls, sessiontype: Type[bs.Session]) -> bool:
|
||||||
return issubclass(sessiontype, ba.DualTeamSession)
|
return issubclass(sessiontype, bs.DualTeamSession)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
|
def get_supported_maps(cls, sessiontype: Type[bs.Session]) -> List[str]:
|
||||||
return ['Open Field', 'Closed Arena']
|
return ['Open Field', 'Closed Arena']
|
||||||
|
|
||||||
def __init__(self, settings: dict):
|
def __init__(self, settings: dict):
|
||||||
super().__init__(settings)
|
super().__init__(settings)
|
||||||
shared = SharedObjects.get()
|
shared = SharedObjects.get()
|
||||||
self._scoreboard = Scoreboard()
|
self._scoreboard = Scoreboard()
|
||||||
self._cheer_sound = ba.getsound('cheer')
|
self._cheer_sound = bs.getsound('cheer')
|
||||||
self._chant_sound = ba.getsound('crowdChant')
|
self._chant_sound = bs.getsound('crowdChant')
|
||||||
self._foghorn_sound = ba.getsound('foghorn')
|
self._foghorn_sound = bs.getsound('foghorn')
|
||||||
self._swipsound = ba.getsound('swip')
|
self._swipsound = bs.getsound('swip')
|
||||||
self._whistle_sound = ba.getsound('refWhistle')
|
self._whistle_sound = bs.getsound('refWhistle')
|
||||||
self.puck_model = ba.getmodel('shield')
|
self.puck_mesh = bs.getmesh('shield')
|
||||||
self.puck_tex = ba.gettexture('gameCircleIcon')
|
self.puck_tex = bs.gettexture('gameCircleIcon')
|
||||||
self._puck_sound = ba.getsound('metalHit')
|
self._puck_sound = bs.getsound('metalHit')
|
||||||
self.puck_material = ba.Material()
|
self.puck_material = bs.Material()
|
||||||
self.puck_material.add_actions(actions=(('modify_part_collision',
|
self.puck_material.add_actions(actions=(('modify_part_collision',
|
||||||
'friction', 0.5)))
|
'friction', 0.5)))
|
||||||
self.puck_material.add_actions(conditions=('they_have_material',
|
self.puck_material.add_actions(conditions=('they_have_material',
|
||||||
|
|
@ -233,16 +232,16 @@ class VolleyBallGame(ba.TeamGameActivity[Player, Team]):
|
||||||
conditions=('they_have_material',
|
conditions=('they_have_material',
|
||||||
PowerupBoxFactory.get().powerup_material),
|
PowerupBoxFactory.get().powerup_material),
|
||||||
actions=(('modify_part_collision', 'physical', False),
|
actions=(('modify_part_collision', 'physical', False),
|
||||||
('message', 'their_node', 'at_connect', ba.DieMessage())))
|
('message', 'their_node', 'at_connect', bs.DieMessage())))
|
||||||
self._score_region_material = ba.Material()
|
self._score_region_material = bs.Material()
|
||||||
self._score_region_material.add_actions(
|
self._score_region_material.add_actions(
|
||||||
conditions=('they_have_material', self.puck_material),
|
conditions=('they_have_material', self.puck_material),
|
||||||
actions=(('modify_part_collision', 'collide',
|
actions=(('modify_part_collision', 'collide',
|
||||||
True), ('modify_part_collision', 'physical', False),
|
True), ('modify_part_collision', 'physical', False),
|
||||||
('call', 'at_connect', self._handle_score)))
|
('call', 'at_connect', self._handle_score)))
|
||||||
|
|
||||||
self._wall_material = ba.Material()
|
self._wall_material = bs.Material()
|
||||||
self._fake_wall_material = ba.Material()
|
self._fake_wall_material = bs.Material()
|
||||||
self._wall_material.add_actions(
|
self._wall_material.add_actions(
|
||||||
|
|
||||||
actions=(
|
actions=(
|
||||||
|
|
@ -282,7 +281,7 @@ class VolleyBallGame(ba.TeamGameActivity[Player, Team]):
|
||||||
))
|
))
|
||||||
self.blocks = []
|
self.blocks = []
|
||||||
|
|
||||||
self._net_wall_material = ba.Material()
|
self._net_wall_material = bs.Material()
|
||||||
self._net_wall_material.add_actions(
|
self._net_wall_material.add_actions(
|
||||||
conditions=('they_have_material', shared.player_material),
|
conditions=('they_have_material', shared.player_material),
|
||||||
actions=(
|
actions=(
|
||||||
|
|
@ -309,7 +308,7 @@ class VolleyBallGame(ba.TeamGameActivity[Player, Team]):
|
||||||
self.net_blocc = []
|
self.net_blocc = []
|
||||||
|
|
||||||
self._puck_spawn_pos: Optional[Sequence[float]] = None
|
self._puck_spawn_pos: Optional[Sequence[float]] = None
|
||||||
self._score_regions: Optional[List[ba.NodeActor]] = None
|
self._score_regions: Optional[List[bs.NodeActor]] = None
|
||||||
self._puck: Optional[Puck] = None
|
self._puck: Optional[Puck] = None
|
||||||
self._score_to_win = int(settings['Score to Win'])
|
self._score_to_win = int(settings['Score to Win'])
|
||||||
self._punchie_ = bool(settings['Disable Punch'])
|
self._punchie_ = bool(settings['Disable Punch'])
|
||||||
|
|
@ -321,8 +320,8 @@ class VolleyBallGame(ba.TeamGameActivity[Player, Team]):
|
||||||
self._epic_mode = bool(settings['Epic Mode'])
|
self._epic_mode = bool(settings['Epic Mode'])
|
||||||
# Base class overrides.
|
# Base class overrides.
|
||||||
self.slow_motion = self._epic_mode
|
self.slow_motion = self._epic_mode
|
||||||
self.default_music = (ba.MusicType.EPIC if self._epic_mode else
|
self.default_music = (bs.MusicType.EPIC if self._epic_mode else
|
||||||
ba.MusicType.TO_THE_DEATH)
|
bs.MusicType.TO_THE_DEATH)
|
||||||
|
|
||||||
def get_instance_description(self) -> Union[str, Sequence]:
|
def get_instance_description(self) -> Union[str, Sequence]:
|
||||||
if self._score_to_win == 1:
|
if self._score_to_win == 1:
|
||||||
|
|
@ -339,15 +338,15 @@ class VolleyBallGame(ba.TeamGameActivity[Player, Team]):
|
||||||
|
|
||||||
self.setup_standard_time_limit(self._time_limit)
|
self.setup_standard_time_limit(self._time_limit)
|
||||||
if self._night_mode:
|
if self._night_mode:
|
||||||
ba.getactivity().globalsnode.tint = (0.5, 0.7, 1)
|
bs.getactivity().globalsnode.tint = (0.5, 0.7, 1)
|
||||||
self._puck_spawn_pos = self.map.get_flag_position(None)
|
self._puck_spawn_pos = self.map.get_flag_position(None)
|
||||||
self._spawn_puck()
|
self._spawn_puck()
|
||||||
|
|
||||||
# Set up the two score regions.
|
# Set up the two score regions.
|
||||||
self._score_regions = []
|
self._score_regions = []
|
||||||
self._score_regions.append(
|
self._score_regions.append(
|
||||||
ba.NodeActor(
|
bs.NodeActor(
|
||||||
ba.newnode('region',
|
bs.newnode('region',
|
||||||
attrs={
|
attrs={
|
||||||
'position': (5.7, 0, -0.065),
|
'position': (5.7, 0, -0.065),
|
||||||
'scale': (10.7, 0.001, 8),
|
'scale': (10.7, 0.001, 8),
|
||||||
|
|
@ -355,8 +354,8 @@ class VolleyBallGame(ba.TeamGameActivity[Player, Team]):
|
||||||
'materials': [self._score_region_material]
|
'materials': [self._score_region_material]
|
||||||
})))
|
})))
|
||||||
self._score_regions.append(
|
self._score_regions.append(
|
||||||
ba.NodeActor(
|
bs.NodeActor(
|
||||||
ba.newnode('region',
|
bs.newnode('region',
|
||||||
attrs={
|
attrs={
|
||||||
'position': (-5.7, 0, -0.065),
|
'position': (-5.7, 0, -0.065),
|
||||||
'scale': (10.7, 0.001, 8),
|
'scale': (10.7, 0.001, 8),
|
||||||
|
|
@ -364,9 +363,9 @@ class VolleyBallGame(ba.TeamGameActivity[Player, Team]):
|
||||||
'materials': [self._score_region_material]
|
'materials': [self._score_region_material]
|
||||||
})))
|
})))
|
||||||
self._update_scoreboard()
|
self._update_scoreboard()
|
||||||
ba.playsound(self._chant_sound)
|
self._chant_sound.play()
|
||||||
if self.credit_text:
|
if self.credit_text:
|
||||||
t = ba.newnode('text',
|
t = bs.newnode('text',
|
||||||
attrs={'text': "Created by Freaku\nVolleyBall", # Disable 'Enable Bottom Credits' when making playlist, No need to edit this lovely...
|
attrs={'text': "Created by Freaku\nVolleyBall", # Disable 'Enable Bottom Credits' when making playlist, No need to edit this lovely...
|
||||||
'scale': 0.7,
|
'scale': 0.7,
|
||||||
'position': (0, 0),
|
'position': (0, 0),
|
||||||
|
|
@ -376,23 +375,23 @@ class VolleyBallGame(ba.TeamGameActivity[Player, Team]):
|
||||||
'h_align': 'center',
|
'h_align': 'center',
|
||||||
'v_attach': 'bottom'})
|
'v_attach': 'bottom'})
|
||||||
shared = SharedObjects.get()
|
shared = SharedObjects.get()
|
||||||
self.blocks.append(ba.NodeActor(ba.newnode('region', attrs={'position': (0, 2.4, 0), 'scale': (
|
self.blocks.append(bs.NodeActor(bs.newnode('region', attrs={'position': (0, 2.4, 0), 'scale': (
|
||||||
0.8, 6, 20), 'type': 'box', 'materials': (self._fake_wall_material, )})))
|
0.8, 6, 20), 'type': 'box', 'materials': (self._fake_wall_material, )})))
|
||||||
|
|
||||||
self.net_blocc.append(ba.NodeActor(ba.newnode('region', attrs={'position': (0, 0, 0), 'scale': (
|
self.net_blocc.append(bs.NodeActor(bs.newnode('region', attrs={'position': (0, 0, 0), 'scale': (
|
||||||
0.6, 2.4, 20), 'type': 'box', 'materials': (self._net_wall_material, )})))
|
0.6, 2.4, 20), 'type': 'box', 'materials': (self._net_wall_material, )})))
|
||||||
|
|
||||||
def on_team_join(self, team: Team) -> None:
|
def on_team_join(self, team: Team) -> None:
|
||||||
self._update_scoreboard()
|
self._update_scoreboard()
|
||||||
|
|
||||||
def _handle_puck_player_collide(self) -> None:
|
def _handle_puck_player_collide(self) -> None:
|
||||||
collision = ba.getcollision()
|
collision = bs.getcollision()
|
||||||
try:
|
try:
|
||||||
puck = collision.sourcenode.getdelegate(Puck, True)
|
puck = collision.sourcenode.getdelegate(Puck, True)
|
||||||
player = collision.opposingnode.getdelegate(PlayerSpaz,
|
player = collision.opposingnode.getdelegate(PlayerSpaz,
|
||||||
True).getplayer(
|
True).getplayer(
|
||||||
Player, True)
|
Player, True)
|
||||||
except ba.NotFoundError:
|
except bs.NotFoundError:
|
||||||
return
|
return
|
||||||
|
|
||||||
puck.last_players_to_touch[player.team.id] = player
|
puck.last_players_to_touch[player.team.id] = player
|
||||||
|
|
@ -409,7 +408,7 @@ class VolleyBallGame(ba.TeamGameActivity[Player, Team]):
|
||||||
if self._puck.scored:
|
if self._puck.scored:
|
||||||
return
|
return
|
||||||
|
|
||||||
region = ba.getcollision().sourcenode
|
region = bs.getcollision().sourcenode
|
||||||
index = 0
|
index = 0
|
||||||
for index in range(len(self._score_regions)):
|
for index in range(len(self._score_regions)):
|
||||||
if region == self._score_regions[index].node:
|
if region == self._score_regions[index].node:
|
||||||
|
|
@ -431,7 +430,7 @@ class VolleyBallGame(ba.TeamGameActivity[Player, Team]):
|
||||||
|
|
||||||
for player in team.players:
|
for player in team.players:
|
||||||
if player.actor:
|
if player.actor:
|
||||||
player.actor.handlemessage(ba.CelebrateMessage(2.0))
|
player.actor.handlemessage(bs.CelebrateMessage(2.0))
|
||||||
|
|
||||||
# If we've got the player from the scoring team that last
|
# If we've got the player from the scoring team that last
|
||||||
# touched us, give them points.
|
# touched us, give them points.
|
||||||
|
|
@ -446,28 +445,28 @@ class VolleyBallGame(ba.TeamGameActivity[Player, Team]):
|
||||||
if team.score >= self._score_to_win:
|
if team.score >= self._score_to_win:
|
||||||
self.end_game()
|
self.end_game()
|
||||||
|
|
||||||
ba.playsound(self._foghorn_sound)
|
self._foghorn_sound.play()
|
||||||
ba.playsound(self._cheer_sound)
|
self._cheer_sound.play()
|
||||||
|
|
||||||
self._puck.scored = True
|
self._puck.scored = True
|
||||||
|
|
||||||
# Kill the puck (it'll respawn itself shortly).
|
# Kill the puck (it'll respawn itself shortly).
|
||||||
ba.emitfx(position=ba.getcollision().position, count=int(
|
bs.emitfx(position=bs.getcollision().position, count=int(
|
||||||
6.0 + 7.0 * 12), scale=3, spread=0.5, chunk_type='spark')
|
6.0 + 7.0 * 12), scale=3, spread=0.5, chunk_type='spark')
|
||||||
ba.timer(0.7, self._kill_puck)
|
bs.timer(0.7, self._kill_puck)
|
||||||
|
|
||||||
ba.cameraflash(duration=7.0)
|
bs.cameraflash(duration=7.0)
|
||||||
self._update_scoreboard()
|
self._update_scoreboard()
|
||||||
|
|
||||||
def end_game(self) -> None:
|
def end_game(self) -> None:
|
||||||
results = ba.GameResults()
|
results = bs.GameResults()
|
||||||
for team in self.teams:
|
for team in self.teams:
|
||||||
results.set_team_score(team, team.score)
|
results.set_team_score(team, team.score)
|
||||||
self.end(results=results)
|
self.end(results=results)
|
||||||
|
|
||||||
def on_transition_in(self) -> None:
|
def on_transition_in(self) -> None:
|
||||||
super().on_transition_in()
|
super().on_transition_in()
|
||||||
activity = ba.getactivity()
|
activity = bs.getactivity()
|
||||||
if self._icy_flooor:
|
if self._icy_flooor:
|
||||||
activity.map.is_hockey = True
|
activity.map.is_hockey = True
|
||||||
|
|
||||||
|
|
@ -477,7 +476,7 @@ class VolleyBallGame(ba.TeamGameActivity[Player, Team]):
|
||||||
self._scoreboard.set_team_value(team, team.score, winscore)
|
self._scoreboard.set_team_value(team, team.score, winscore)
|
||||||
|
|
||||||
# overriding the default character spawning..
|
# overriding the default character spawning..
|
||||||
def spawn_player(self, player: Player) -> ba.Actor:
|
def spawn_player(self, player: Player) -> bs.Actor:
|
||||||
spaz = self.spawn_player_spaz(player)
|
spaz = self.spawn_player_spaz(player)
|
||||||
|
|
||||||
if self._bombies_:
|
if self._bombies_:
|
||||||
|
|
@ -493,7 +492,7 @@ class VolleyBallGame(ba.TeamGameActivity[Player, Team]):
|
||||||
def handlemessage(self, msg: Any) -> Any:
|
def handlemessage(self, msg: Any) -> Any:
|
||||||
|
|
||||||
# Respawn dead players if they're still in the game.
|
# Respawn dead players if they're still in the game.
|
||||||
if isinstance(msg, ba.PlayerDiedMessage):
|
if isinstance(msg, bs.PlayerDiedMessage):
|
||||||
# Augment standard behavior...
|
# Augment standard behavior...
|
||||||
super().handlemessage(msg)
|
super().handlemessage(msg)
|
||||||
self.respawn_player(msg.getplayer(Player))
|
self.respawn_player(msg.getplayer(Player))
|
||||||
|
|
@ -501,18 +500,18 @@ class VolleyBallGame(ba.TeamGameActivity[Player, Team]):
|
||||||
# Respawn dead pucks.
|
# Respawn dead pucks.
|
||||||
elif isinstance(msg, PuckDiedMessage):
|
elif isinstance(msg, PuckDiedMessage):
|
||||||
if not self.has_ended():
|
if not self.has_ended():
|
||||||
ba.timer(2.2, self._spawn_puck)
|
bs.timer(2.2, self._spawn_puck)
|
||||||
else:
|
else:
|
||||||
super().handlemessage(msg)
|
super().handlemessage(msg)
|
||||||
|
|
||||||
def _flash_puck_spawn(self) -> None:
|
def _flash_puck_spawn(self) -> None:
|
||||||
# Effect >>>>>> Flashly
|
# Effect >>>>>> Flashly
|
||||||
ba.emitfx(position=self._puck_spawn_pos, count=int(
|
bs.emitfx(position=self._puck_spawn_pos, count=int(
|
||||||
6.0 + 7.0 * 12), scale=1.7, spread=0.4, chunk_type='spark')
|
6.0 + 7.0 * 12), scale=1.7, spread=0.4, chunk_type='spark')
|
||||||
|
|
||||||
def _spawn_puck(self) -> None:
|
def _spawn_puck(self) -> None:
|
||||||
ba.playsound(self._swipsound)
|
self._swipsound.play()
|
||||||
ba.playsound(self._whistle_sound)
|
self._whistle_sound.play()
|
||||||
self._flash_puck_spawn()
|
self._flash_puck_spawn()
|
||||||
assert self._puck_spawn_pos is not None
|
assert self._puck_spawn_pos is not None
|
||||||
self._puck = Puck(position=self._puck_spawn_pos)
|
self._puck = Puck(position=self._puck_spawn_pos)
|
||||||
|
|
@ -538,7 +537,7 @@ class PointzzforH:
|
||||||
points['spawn2'] = (6.857415055, 0.03938567998, 0.0) + (1.0, 1.0, 3.0)
|
points['spawn2'] = (6.857415055, 0.03938567998, 0.0) + (1.0, 1.0, 3.0)
|
||||||
|
|
||||||
|
|
||||||
class VolleyBallMap(ba.Map):
|
class VolleyBallMap(bs.Map):
|
||||||
defs = Pointzz()
|
defs = Pointzz()
|
||||||
name = "Open Field"
|
name = "Open Field"
|
||||||
|
|
||||||
|
|
@ -553,10 +552,10 @@ class VolleyBallMap(ba.Map):
|
||||||
@classmethod
|
@classmethod
|
||||||
def on_preload(cls) -> Any:
|
def on_preload(cls) -> Any:
|
||||||
data: Dict[str, Any] = {
|
data: Dict[str, Any] = {
|
||||||
'model': ba.getmodel('footballStadium'),
|
'mesh': bs.getmesh('footballStadium'),
|
||||||
'vr_fill_model': ba.getmodel('footballStadiumVRFill'),
|
'vr_fill_mesh': bs.getmesh('footballStadiumVRFill'),
|
||||||
'collide_model': ba.getcollidemodel('footballStadiumCollide'),
|
'collision_mesh': bs.getcollisionmesh('footballStadiumCollide'),
|
||||||
'tex': ba.gettexture('footballStadium')
|
'tex': bs.gettexture('footballStadium')
|
||||||
}
|
}
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
@ -565,60 +564,60 @@ class VolleyBallMap(ba.Map):
|
||||||
shared = SharedObjects.get()
|
shared = SharedObjects.get()
|
||||||
x = -5
|
x = -5
|
||||||
while x < 5:
|
while x < 5:
|
||||||
self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (0, 0, x),
|
self.zone = bs.newnode('locator', attrs={'shape': 'circle', 'position': (0, 0, x),
|
||||||
'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
||||||
self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (0, .25, x),
|
self.zone = bs.newnode('locator', attrs={'shape': 'circle', 'position': (0, .25, x),
|
||||||
'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
||||||
self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (0, .5, x),
|
self.zone = bs.newnode('locator', attrs={'shape': 'circle', 'position': (0, .5, x),
|
||||||
'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
||||||
self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (0, .75, x),
|
self.zone = bs.newnode('locator', attrs={'shape': 'circle', 'position': (0, .75, x),
|
||||||
'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
||||||
self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (0, 1, x),
|
self.zone = bs.newnode('locator', attrs={'shape': 'circle', 'position': (0, 1, x),
|
||||||
'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
||||||
x = x + 0.5
|
x = x + 0.5
|
||||||
|
|
||||||
y = -1
|
y = -1
|
||||||
while y > -11:
|
while y > -11:
|
||||||
self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (y, 0.01, 4),
|
self.zone = bs.newnode('locator', attrs={'shape': 'circle', 'position': (y, 0.01, 4),
|
||||||
'color': (0, 0, 1), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
'color': (0, 0, 1), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
||||||
self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (y, 0.01, -4),
|
self.zone = bs.newnode('locator', attrs={'shape': 'circle', 'position': (y, 0.01, -4),
|
||||||
'color': (0, 0, 1), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
'color': (0, 0, 1), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
||||||
self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (-y, 0.01, 4),
|
self.zone = bs.newnode('locator', attrs={'shape': 'circle', 'position': (-y, 0.01, 4),
|
||||||
'color': (1, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
'color': (1, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
||||||
self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (-y, 0.01, -4),
|
self.zone = bs.newnode('locator', attrs={'shape': 'circle', 'position': (-y, 0.01, -4),
|
||||||
'color': (1, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
'color': (1, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
||||||
y -= 1
|
y -= 1
|
||||||
|
|
||||||
z = 0
|
z = 0
|
||||||
while z < 5:
|
while z < 5:
|
||||||
self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (11, 0.01, z),
|
self.zone = bs.newnode('locator', attrs={'shape': 'circle', 'position': (11, 0.01, z),
|
||||||
'color': (1, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
'color': (1, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
||||||
self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (11, 0.01, -z),
|
self.zone = bs.newnode('locator', attrs={'shape': 'circle', 'position': (11, 0.01, -z),
|
||||||
'color': (1, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
'color': (1, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
||||||
self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (-11, 0.01, z),
|
self.zone = bs.newnode('locator', attrs={'shape': 'circle', 'position': (-11, 0.01, z),
|
||||||
'color': (0, 0, 1), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
'color': (0, 0, 1), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
||||||
self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (-11, 0.01, -z),
|
self.zone = bs.newnode('locator', attrs={'shape': 'circle', 'position': (-11, 0.01, -z),
|
||||||
'color': (0, 0, 1), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
'color': (0, 0, 1), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
||||||
z += 1
|
z += 1
|
||||||
|
|
||||||
self.node = ba.newnode(
|
self.node = bs.newnode(
|
||||||
'terrain',
|
'terrain',
|
||||||
delegate=self,
|
delegate=self,
|
||||||
attrs={
|
attrs={
|
||||||
'model': self.preloaddata['model'],
|
'mesh': self.preloaddata['mesh'],
|
||||||
'collide_model': self.preloaddata['collide_model'],
|
'collision_mesh': self.preloaddata['collision_mesh'],
|
||||||
'color_texture': self.preloaddata['tex'],
|
'color_texture': self.preloaddata['tex'],
|
||||||
'materials': [shared.footing_material]
|
'materials': [shared.footing_material]
|
||||||
})
|
})
|
||||||
ba.newnode('terrain',
|
bs.newnode('terrain',
|
||||||
attrs={
|
attrs={
|
||||||
'model': self.preloaddata['vr_fill_model'],
|
'mesh': self.preloaddata['vr_fill_mesh'],
|
||||||
'lighting': False,
|
'lighting': False,
|
||||||
'vr_only': True,
|
'vr_only': True,
|
||||||
'background': True,
|
'background': True,
|
||||||
'color_texture': self.preloaddata['tex']
|
'color_texture': self.preloaddata['tex']
|
||||||
})
|
})
|
||||||
gnode = ba.getactivity().globalsnode
|
gnode = bs.getactivity().globalsnode
|
||||||
gnode.tint = (1.3, 1.2, 1.0)
|
gnode.tint = (1.3, 1.2, 1.0)
|
||||||
gnode.ambient_color = (1.3, 1.2, 1.0)
|
gnode.ambient_color = (1.3, 1.2, 1.0)
|
||||||
gnode.vignette_outer = (0.57, 0.57, 0.57)
|
gnode.vignette_outer = (0.57, 0.57, 0.57)
|
||||||
|
|
@ -627,7 +626,7 @@ class VolleyBallMap(ba.Map):
|
||||||
gnode.vr_near_clip = 0.5
|
gnode.vr_near_clip = 0.5
|
||||||
|
|
||||||
|
|
||||||
class VolleyBallMapH(ba.Map):
|
class VolleyBallMapH(bs.Map):
|
||||||
defs = PointzzforH()
|
defs = PointzzforH()
|
||||||
name = 'Closed Arena'
|
name = 'Closed Arena'
|
||||||
|
|
||||||
|
|
@ -642,13 +641,13 @@ class VolleyBallMapH(ba.Map):
|
||||||
@classmethod
|
@classmethod
|
||||||
def on_preload(cls) -> Any:
|
def on_preload(cls) -> Any:
|
||||||
data: Dict[str, Any] = {
|
data: Dict[str, Any] = {
|
||||||
'models': (ba.getmodel('hockeyStadiumOuter'),
|
'meshs': (bs.getmesh('hockeyStadiumOuter'),
|
||||||
ba.getmodel('hockeyStadiumInner')),
|
bs.getmesh('hockeyStadiumInner')),
|
||||||
'vr_fill_model': ba.getmodel('footballStadiumVRFill'),
|
'vr_fill_mesh': bs.getmesh('footballStadiumVRFill'),
|
||||||
'collide_model': ba.getcollidemodel('hockeyStadiumCollide'),
|
'collision_mesh': bs.getcollisionmesh('hockeyStadiumCollide'),
|
||||||
'tex': ba.gettexture('hockeyStadium'),
|
'tex': bs.gettexture('hockeyStadium'),
|
||||||
}
|
}
|
||||||
mat = ba.Material()
|
mat = bs.Material()
|
||||||
mat.add_actions(actions=('modify_part_collision', 'friction', 0.01))
|
mat.add_actions(actions=('modify_part_collision', 'friction', 0.01))
|
||||||
data['ice_material'] = mat
|
data['ice_material'] = mat
|
||||||
return data
|
return data
|
||||||
|
|
@ -658,66 +657,66 @@ class VolleyBallMapH(ba.Map):
|
||||||
shared = SharedObjects.get()
|
shared = SharedObjects.get()
|
||||||
x = -5
|
x = -5
|
||||||
while x < 5:
|
while x < 5:
|
||||||
self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (0, 0, x),
|
self.zone = bs.newnode('locator', attrs={'shape': 'circle', 'position': (0, 0, x),
|
||||||
'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
||||||
self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (0, .25, x),
|
self.zone = bs.newnode('locator', attrs={'shape': 'circle', 'position': (0, .25, x),
|
||||||
'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
||||||
self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (0, .5, x),
|
self.zone = bs.newnode('locator', attrs={'shape': 'circle', 'position': (0, .5, x),
|
||||||
'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
||||||
self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (0, .75, x),
|
self.zone = bs.newnode('locator', attrs={'shape': 'circle', 'position': (0, .75, x),
|
||||||
'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
||||||
self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (0, 1, x),
|
self.zone = bs.newnode('locator', attrs={'shape': 'circle', 'position': (0, 1, x),
|
||||||
'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
'color': (1, 1, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
||||||
x = x + 0.5
|
x = x + 0.5
|
||||||
|
|
||||||
y = -1
|
y = -1
|
||||||
while y > -11:
|
while y > -11:
|
||||||
self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (y, 0.01, 4),
|
self.zone = bs.newnode('locator', attrs={'shape': 'circle', 'position': (y, 0.01, 4),
|
||||||
'color': (0, 0, 1), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
'color': (0, 0, 1), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
||||||
self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (y, 0.01, -4),
|
self.zone = bs.newnode('locator', attrs={'shape': 'circle', 'position': (y, 0.01, -4),
|
||||||
'color': (0, 0, 1), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
'color': (0, 0, 1), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
||||||
self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (-y, 0.01, 4),
|
self.zone = bs.newnode('locator', attrs={'shape': 'circle', 'position': (-y, 0.01, 4),
|
||||||
'color': (1, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
'color': (1, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
||||||
self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (-y, 0.01, -4),
|
self.zone = bs.newnode('locator', attrs={'shape': 'circle', 'position': (-y, 0.01, -4),
|
||||||
'color': (1, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
'color': (1, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
||||||
y -= 1
|
y -= 1
|
||||||
|
|
||||||
z = 0
|
z = 0
|
||||||
while z < 5:
|
while z < 5:
|
||||||
self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (11, 0.01, z),
|
self.zone = bs.newnode('locator', attrs={'shape': 'circle', 'position': (11, 0.01, z),
|
||||||
'color': (1, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
'color': (1, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
||||||
self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (11, 0.01, -z),
|
self.zone = bs.newnode('locator', attrs={'shape': 'circle', 'position': (11, 0.01, -z),
|
||||||
'color': (1, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
'color': (1, 0, 0), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
||||||
self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (-11, 0.01, z),
|
self.zone = bs.newnode('locator', attrs={'shape': 'circle', 'position': (-11, 0.01, z),
|
||||||
'color': (0, 0, 1), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
'color': (0, 0, 1), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
||||||
self.zone = ba.newnode('locator', attrs={'shape': 'circle', 'position': (-11, 0.01, -z),
|
self.zone = bs.newnode('locator', attrs={'shape': 'circle', 'position': (-11, 0.01, -z),
|
||||||
'color': (0, 0, 1), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
'color': (0, 0, 1), 'opacity': 1, 'draw_beauty': True, 'additive': False, 'size': [0.40]})
|
||||||
z += 1
|
z += 1
|
||||||
|
|
||||||
self.node = ba.newnode('terrain',
|
self.node = bs.newnode('terrain',
|
||||||
delegate=self,
|
delegate=self,
|
||||||
attrs={
|
attrs={
|
||||||
'model':
|
'mesh':
|
||||||
None,
|
None,
|
||||||
'collide_model':
|
'collision_mesh':
|
||||||
# we dont want Goalposts...
|
# we dont want Goalposts...
|
||||||
ba.getcollidemodel('footballStadiumCollide'),
|
bs.getcollisionmesh('footballStadiumCollide'),
|
||||||
'color_texture':
|
'color_texture':
|
||||||
self.preloaddata['tex'],
|
self.preloaddata['tex'],
|
||||||
'materials': [
|
'materials': [
|
||||||
shared.footing_material]
|
shared.footing_material]
|
||||||
})
|
})
|
||||||
ba.newnode('terrain',
|
bs.newnode('terrain',
|
||||||
attrs={
|
attrs={
|
||||||
'model': self.preloaddata['vr_fill_model'],
|
'mesh': self.preloaddata['vr_fill_mesh'],
|
||||||
'vr_only': True,
|
'vr_only': True,
|
||||||
'lighting': False,
|
'lighting': False,
|
||||||
'background': True,
|
'background': True,
|
||||||
})
|
})
|
||||||
mats = [shared.footing_material]
|
mats = [shared.footing_material]
|
||||||
self.floor = ba.newnode('terrain',
|
self.floor = bs.newnode('terrain',
|
||||||
attrs={
|
attrs={
|
||||||
'model': self.preloaddata['models'][1],
|
'mesh': self.preloaddata['meshs'][1],
|
||||||
'color_texture': self.preloaddata['tex'],
|
'color_texture': self.preloaddata['tex'],
|
||||||
'opacity': 0.92,
|
'opacity': 0.92,
|
||||||
'opacity_in_low_or_medium_quality': 1.0,
|
'opacity_in_low_or_medium_quality': 1.0,
|
||||||
|
|
@ -725,16 +724,16 @@ class VolleyBallMapH(ba.Map):
|
||||||
'color': (0.4, 0.9, 0)
|
'color': (0.4, 0.9, 0)
|
||||||
})
|
})
|
||||||
|
|
||||||
self.background = ba.newnode(
|
self.background = bs.newnode(
|
||||||
'terrain',
|
'terrain',
|
||||||
attrs={
|
attrs={
|
||||||
'model': ba.getmodel('natureBackground'),
|
'mesh': bs.getmesh('natureBackground'),
|
||||||
'lighting': False,
|
'lighting': False,
|
||||||
'background': True,
|
'background': True,
|
||||||
'color': (0.5, 0.30, 0.4)
|
'color': (0.5, 0.30, 0.4)
|
||||||
})
|
})
|
||||||
|
|
||||||
gnode = ba.getactivity().globalsnode
|
gnode = bs.getactivity().globalsnode
|
||||||
gnode.floor_reflection = True
|
gnode.floor_reflection = True
|
||||||
gnode.debris_friction = 0.3
|
gnode.debris_friction = 0.3
|
||||||
gnode.debris_kill_height = -0.3
|
gnode.debris_kill_height = -0.3
|
||||||
|
|
@ -747,5 +746,17 @@ class VolleyBallMapH(ba.Map):
|
||||||
#self.is_hockey = True
|
#self.is_hockey = True
|
||||||
|
|
||||||
|
|
||||||
ba._map.register_map(VolleyBallMap)
|
bs._map.register_map(VolleyBallMap)
|
||||||
ba._map.register_map(VolleyBallMapH)
|
bs._map.register_map(VolleyBallMapH)
|
||||||
|
|
||||||
|
|
||||||
|
# ba_meta export plugin
|
||||||
|
class byFreaku(babase.Plugin):
|
||||||
|
def __init__(self):
|
||||||
|
# Reason of plugin:
|
||||||
|
# To register maps.
|
||||||
|
#
|
||||||
|
# Then why not include function here?
|
||||||
|
# On server upon first launch, plugins are not activated,
|
||||||
|
# (same can be case for user if disabled auto-enable plugins)
|
||||||
|
pass
|
||||||
|
|
|
||||||
|
|
@ -293,10 +293,16 @@
|
||||||
{
|
{
|
||||||
"name": "Freaku",
|
"name": "Freaku",
|
||||||
"email": "",
|
"email": "",
|
||||||
"discord": "[Just] Freak#4999"
|
"discord": ""
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"versions": {
|
"versions": {
|
||||||
|
"2.0.0": {
|
||||||
|
"api_version": 8,
|
||||||
|
"commit_sha": "48f9302",
|
||||||
|
"released_on": "28-07-2023",
|
||||||
|
"md5sum": "31df84f027c98e86336a420aa509e47f"
|
||||||
|
},
|
||||||
"1.0.0": {
|
"1.0.0": {
|
||||||
"api_version": 7,
|
"api_version": 7,
|
||||||
"commit_sha": "6beb8ddf",
|
"commit_sha": "6beb8ddf",
|
||||||
|
|
@ -312,10 +318,16 @@
|
||||||
{
|
{
|
||||||
"name": "Freaku",
|
"name": "Freaku",
|
||||||
"email": "",
|
"email": "",
|
||||||
"discord": "[Just] Freak#4999"
|
"discord": ""
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"versions": {
|
"versions": {
|
||||||
|
"2.0.0": {
|
||||||
|
"api_version": 8,
|
||||||
|
"commit_sha": "48f9302",
|
||||||
|
"released_on": "28-07-2023",
|
||||||
|
"md5sum": "ef2dbcac9190a61753e2c3c0f8afc22c"
|
||||||
|
},
|
||||||
"1.1.0": {
|
"1.1.0": {
|
||||||
"api_version": 7,
|
"api_version": 7,
|
||||||
"commit_sha": "383f774",
|
"commit_sha": "383f774",
|
||||||
|
|
@ -505,10 +517,16 @@
|
||||||
{
|
{
|
||||||
"name": "Freaku",
|
"name": "Freaku",
|
||||||
"email": "",
|
"email": "",
|
||||||
"discord": "[Just] Freak#4999"
|
"discord": ""
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"versions": {
|
"versions": {
|
||||||
|
"2.0.0": {
|
||||||
|
"api_version": 8,
|
||||||
|
"commit_sha": "48f9302",
|
||||||
|
"released_on": "28-07-2023",
|
||||||
|
"md5sum": "8a63ad58d24e2b61bb63645f74d876e8"
|
||||||
|
},
|
||||||
"1.0.0": {
|
"1.0.0": {
|
||||||
"api_version": 7,
|
"api_version": 7,
|
||||||
"commit_sha": "b581d90",
|
"commit_sha": "b581d90",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Ported by: Freaku / @[Just] Freak#4999
|
# Ported by your friend: Freaku
|
||||||
|
|
||||||
# Join BCS:
|
# Join BCS:
|
||||||
# https://discord.gg/ucyaesh
|
# https://discord.gg/ucyaesh
|
||||||
|
|
@ -8,27 +8,30 @@
|
||||||
# https://github.com/Freaku17/BombSquad-Mods-byFreaku
|
# https://github.com/Freaku17/BombSquad-Mods-byFreaku
|
||||||
|
|
||||||
|
|
||||||
# ba_meta require api 7
|
# ba_meta require api 8
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
import _ba
|
import _babase
|
||||||
import ba
|
import babase
|
||||||
import random
|
import random
|
||||||
import math
|
import math
|
||||||
from bastd.gameutils import SharedObjects
|
import bauiv1 as bui
|
||||||
from bastd.actor.bomb import Bomb
|
import bascenev1 as bs
|
||||||
from bastd.actor.popuptext import PopupText
|
from bascenev1lib.gameutils import SharedObjects
|
||||||
|
from bascenev1lib.actor.bomb import Bomb
|
||||||
|
from bascenev1lib.actor.popuptext import PopupText
|
||||||
|
from bauiv1lib.party import PartyWindow
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
|
||||||
class Floater(ba.Actor):
|
class Floater(bs.Actor):
|
||||||
def __init__(self, bounds):
|
def __init__(self, bounds):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
shared = SharedObjects.get()
|
shared = SharedObjects.get()
|
||||||
self.controlled = False
|
self.controlled = False
|
||||||
self.source_player = None
|
self.source_player = None
|
||||||
self.floaterMaterial = ba.Material()
|
self.floaterMaterial = bs.Material()
|
||||||
self.floaterMaterial.add_actions(
|
self.floaterMaterial.add_actions(
|
||||||
conditions=('they_have_material',
|
conditions=('they_have_material',
|
||||||
shared.player_material),
|
shared.player_material),
|
||||||
|
|
@ -48,21 +51,21 @@ class Floater(ba.Actor):
|
||||||
self.py = "random.uniform(self.pos[1],self.pos[4])"
|
self.py = "random.uniform(self.pos[1],self.pos[4])"
|
||||||
self.pz = "random.uniform(self.pos[2],self.pos[5])"
|
self.pz = "random.uniform(self.pos[2],self.pos[5])"
|
||||||
|
|
||||||
self.node = ba.newnode(
|
self.node = bs.newnode(
|
||||||
'prop',
|
'prop',
|
||||||
delegate=self,
|
delegate=self,
|
||||||
owner=None,
|
owner=None,
|
||||||
attrs={
|
attrs={
|
||||||
'position': (eval(self.px), eval(self.py), eval(self.pz)),
|
'position': (eval(self.px), eval(self.py), eval(self.pz)),
|
||||||
'model':
|
'mesh':
|
||||||
ba.getmodel('landMine'),
|
bs.getmesh('landMine'),
|
||||||
'light_model':
|
'light_mesh':
|
||||||
ba.getmodel('landMine'),
|
bs.getmesh('landMine'),
|
||||||
'body':
|
'body':
|
||||||
'landMine',
|
'landMine',
|
||||||
'body_scale':
|
'body_scale':
|
||||||
3,
|
3,
|
||||||
'model_scale':
|
'mesh_scale':
|
||||||
3.1,
|
3.1,
|
||||||
'shadow_size':
|
'shadow_size':
|
||||||
0.25,
|
0.25,
|
||||||
|
|
@ -71,21 +74,21 @@ class Floater(ba.Actor):
|
||||||
'gravity_scale':
|
'gravity_scale':
|
||||||
0.0,
|
0.0,
|
||||||
'color_texture':
|
'color_texture':
|
||||||
ba.gettexture('achievementFlawlessVictory'),
|
bs.gettexture('achievementFlawlessVictory'),
|
||||||
'reflection':
|
'reflection':
|
||||||
'soft',
|
'soft',
|
||||||
'reflection_scale': [0.25],
|
'reflection_scale': [0.25],
|
||||||
'materials':
|
'materials':
|
||||||
[shared.footing_material, self.floaterMaterial]
|
[shared.footing_material, self.floaterMaterial]
|
||||||
})
|
})
|
||||||
self.node2 = ba.newnode(
|
self.node2 = bs.newnode(
|
||||||
'prop',
|
'prop',
|
||||||
owner=self.node,
|
owner=self.node,
|
||||||
attrs={
|
attrs={
|
||||||
'position': (0, 0, 0),
|
'position': (0, 0, 0),
|
||||||
'body':
|
'body':
|
||||||
'sphere',
|
'sphere',
|
||||||
'model':
|
'mesh':
|
||||||
None,
|
None,
|
||||||
'color_texture':
|
'color_texture':
|
||||||
None,
|
None,
|
||||||
|
|
@ -96,7 +99,7 @@ class Floater(ba.Actor):
|
||||||
'density':
|
'density':
|
||||||
999999,
|
999999,
|
||||||
'reflection_scale': [1.0],
|
'reflection_scale': [1.0],
|
||||||
'model_scale':
|
'mesh_scale':
|
||||||
1.0,
|
1.0,
|
||||||
'gravity_scale':
|
'gravity_scale':
|
||||||
0,
|
0,
|
||||||
|
|
@ -110,7 +113,7 @@ class Floater(ba.Actor):
|
||||||
self.node.connectattr('position', self.node2, 'position')
|
self.node.connectattr('position', self.node2, 'position')
|
||||||
|
|
||||||
def pop(self): PopupText(text="Ported by \ue048Freaku", scale=1.3, position=(
|
def pop(self): PopupText(text="Ported by \ue048Freaku", scale=1.3, position=(
|
||||||
self.node.position[0], self.node.position[1]-1, self.node.position[2]), color=(0, 1, 1)).autoretain() # Edit = YouNoob...
|
self.node.position[0], self.node.position[1]-1, self.node.position[2]), color=(0, 1, 1)).autoretain()
|
||||||
|
|
||||||
def checkCanControl(self):
|
def checkCanControl(self):
|
||||||
if not self.node.exists():
|
if not self.node.exists():
|
||||||
|
|
@ -172,7 +175,7 @@ class Floater(ba.Actor):
|
||||||
if self.source_player is None:
|
if self.source_player is None:
|
||||||
return
|
return
|
||||||
if self.source_player.is_alive():
|
if self.source_player.is_alive():
|
||||||
ba.timer(1, self.checkPlayerDie)
|
bs.timer(1, self.checkPlayerDie)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
self.dis()
|
self.dis()
|
||||||
|
|
@ -199,22 +202,22 @@ class Floater(ba.Actor):
|
||||||
pn = self.node.position
|
pn = self.node.position
|
||||||
dist = self.distance(pn[0], pn[1], pn[2], px, py, pz)
|
dist = self.distance(pn[0], pn[1], pn[2], px, py, pz)
|
||||||
self.node.velocity = ((px - pn[0]) / dist, (py - pn[1]) / dist, (pz - pn[2]) / dist)
|
self.node.velocity = ((px - pn[0]) / dist, (py - pn[1]) / dist, (pz - pn[2]) / dist)
|
||||||
ba.timer(dist-1, ba.WeakCall(self.move), suppress_format_warning=True)
|
bs.timer(dist-1, bs.WeakCall(self.move)) # suppress_format_warning=True)
|
||||||
|
|
||||||
def handlemessage(self, msg):
|
def handlemessage(self, msg):
|
||||||
if isinstance(msg, ba.DieMessage):
|
if isinstance(msg, bs.DieMessage):
|
||||||
self.node.delete()
|
self.node.delete()
|
||||||
self.node2.delete()
|
self.node2.delete()
|
||||||
self.controlled = False
|
self.controlled = False
|
||||||
elif isinstance(msg, ba.OutOfBoundsMessage):
|
elif isinstance(msg, bs.OutOfBoundsMessage):
|
||||||
self.handlemessage(ba.DieMessage())
|
self.handlemessage(bs.DieMessage())
|
||||||
else:
|
else:
|
||||||
super().handlemessage(msg)
|
super().handlemessage(msg)
|
||||||
|
|
||||||
|
|
||||||
def assignFloInputs(clientID: int):
|
def assignFloInputs(clientID: int):
|
||||||
with ba.Context(_ba.get_foreground_host_activity()):
|
activity = bs.get_foreground_host_activity()
|
||||||
activity = ba.getactivity()
|
with activity.context:
|
||||||
if not hasattr(activity, 'flo') or not activity.flo.node.exists():
|
if not hasattr(activity, 'flo') or not activity.flo.node.exists():
|
||||||
try:
|
try:
|
||||||
activity.flo = Floater(activity.map.get_def_bound_box('map_bounds'))
|
activity.flo = Floater(activity.map.get_def_bound_box('map_bounds'))
|
||||||
|
|
@ -222,13 +225,13 @@ def assignFloInputs(clientID: int):
|
||||||
return # Perhaps using in main-menu/score-screen
|
return # Perhaps using in main-menu/score-screen
|
||||||
floater = activity.flo
|
floater = activity.flo
|
||||||
if floater.controlled:
|
if floater.controlled:
|
||||||
ba.screenmessage('Floater is already being controlled',
|
bs.broadcastmessage('Floater is already being controlled',
|
||||||
color=(1, 0, 0), transient=True, clients=[clientID])
|
color=(1, 0, 0), transient=True, clients=[clientID])
|
||||||
return
|
return
|
||||||
ba.screenmessage('You Gained Control Over The Floater!\n Press Bomb to Throw Bombs and Punch to leave!', clients=[
|
bs.broadcastmessage('You Gained Control Over The Floater!\n Press Bomb to Throw Bombs and Punch to leave!', clients=[
|
||||||
clientID], transient=True, color=(0, 1, 1))
|
clientID], transient=True, color=(0, 1, 1))
|
||||||
|
|
||||||
for i in _ba.get_foreground_host_activity().players:
|
for i in activity.players:
|
||||||
if i.sessionplayer.inputdevice.client_id == clientID:
|
if i.sessionplayer.inputdevice.client_id == clientID:
|
||||||
def dis(i, floater):
|
def dis(i, floater):
|
||||||
i.actor.node.invincible = False
|
i.actor.node.invincible = False
|
||||||
|
|
@ -238,41 +241,54 @@ def assignFloInputs(clientID: int):
|
||||||
ps = i.actor.node.position
|
ps = i.actor.node.position
|
||||||
i.actor.node.invincible = True
|
i.actor.node.invincible = True
|
||||||
floater.node.position = (ps[0], ps[1] + 1.0, ps[2])
|
floater.node.position = (ps[0], ps[1] + 1.0, ps[2])
|
||||||
ba.timer(1, floater.pop)
|
bs.timer(1, floater.pop)
|
||||||
i.actor.node.hold_node = ba.Node(None)
|
i.actor.node.hold_node = bs.Node(None)
|
||||||
i.actor.node.hold_node = floater.node2
|
i.actor.node.hold_node = floater.node2
|
||||||
i.actor.connect_controls_to_player()
|
i.actor.connect_controls_to_player()
|
||||||
i.actor.disconnect_controls_from_player()
|
i.actor.disconnect_controls_from_player()
|
||||||
i.resetinput()
|
i.resetinput()
|
||||||
floater.source_player = i
|
floater.source_player = i
|
||||||
floater.con()
|
floater.con()
|
||||||
i.assigninput(ba.InputType.PICK_UP_PRESS, floater.up)
|
i.assigninput(babase.InputType.PICK_UP_PRESS, floater.up)
|
||||||
i.assigninput(ba.InputType.PICK_UP_RELEASE, floater.upR)
|
i.assigninput(babase.InputType.PICK_UP_RELEASE, floater.upR)
|
||||||
i.assigninput(ba.InputType.JUMP_PRESS, floater.down)
|
i.assigninput(babase.InputType.JUMP_PRESS, floater.down)
|
||||||
i.assigninput(ba.InputType.BOMB_PRESS, floater.drop)
|
i.assigninput(babase.InputType.BOMB_PRESS, floater.drop)
|
||||||
i.assigninput(ba.InputType.PUNCH_PRESS, ba.Call(dis, i, floater))
|
i.assigninput(babase.InputType.PUNCH_PRESS, babase.Call(dis, i, floater))
|
||||||
i.assigninput(ba.InputType.UP_DOWN, floater.updown)
|
i.assigninput(babase.InputType.UP_DOWN, floater.updown)
|
||||||
i.assigninput(ba.InputType.LEFT_RIGHT, floater.leftright)
|
i.assigninput(babase.InputType.LEFT_RIGHT, floater.leftright)
|
||||||
|
|
||||||
|
|
||||||
old_fcm = _ba.chatmessage
|
# Display chat icon, but if user open/close gather it may disappear
|
||||||
|
bui.set_party_icon_always_visible(True)
|
||||||
|
|
||||||
|
|
||||||
def new_chat_message(msg: Union[str, ba.Lstr], clients: Sequence[int] = None, sender_override: str = None):
|
old_piv = bui.set_party_icon_always_visible
|
||||||
old_fcm(msg, clients, sender_override)
|
|
||||||
if msg == '/floater':
|
|
||||||
|
def new_piv(*args, **kwargs):
|
||||||
|
# Do not let chat icon go away
|
||||||
|
old_piv(True)
|
||||||
|
|
||||||
|
|
||||||
|
bui.set_party_icon_always_visible = new_piv
|
||||||
|
|
||||||
|
|
||||||
|
old_fcm = bs.chatmessage
|
||||||
|
|
||||||
|
|
||||||
|
def new_chat_message(*args, **kwargs):
|
||||||
|
old_fcm(*args, **kwargs)
|
||||||
|
if args[0] == '/floater':
|
||||||
try:
|
try:
|
||||||
assignFloInputs(-1)
|
assignFloInputs(-1)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
_ba.chatmessage = new_chat_message
|
bs.chatmessage = new_chat_message
|
||||||
if not _ba.is_party_icon_visible():
|
|
||||||
_ba.set_party_icon_always_visible(True)
|
|
||||||
|
|
||||||
# ba_meta export plugin
|
# ba_meta export plugin
|
||||||
|
|
||||||
|
|
||||||
class byFreaku(ba.Plugin):
|
class byFreaku(babase.Plugin):
|
||||||
def __init__(self): pass
|
def __init__(self): pass
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Made by: Freaku / @[Just] Freak#4999
|
# Made by your friend: Freaku
|
||||||
|
|
||||||
# • Icon Keyboard •
|
# • Icon Keyboard •
|
||||||
# Make your chats look even more cooler!
|
# Make your chats look even more cooler!
|
||||||
|
|
@ -6,51 +6,52 @@
|
||||||
# Double tap the space to change between keyboards...
|
# Double tap the space to change between keyboards...
|
||||||
|
|
||||||
|
|
||||||
# ba_meta require api 7
|
# ba_meta require api 8
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import ba
|
import babase
|
||||||
from _ba import charstr as uwu
|
import bascenev1 as bs
|
||||||
|
from babase import charstr as uwu
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any, Optional, Dict, List, Tuple, Type, Iterable
|
from typing import Any, Optional, Dict, List, Tuple, Type, Iterable
|
||||||
|
|
||||||
|
|
||||||
# ba_meta export keyboard
|
# ba_meta export keyboard
|
||||||
class IconKeyboard_byFreaku(ba.Keyboard):
|
class IconKeyboard_byFreaku(babase.Keyboard):
|
||||||
"""Keyboard go brrrrrrr"""
|
"""Keyboard go brrrrrrr"""
|
||||||
name = 'Icons by \ue048Freaku'
|
name = 'Icons by \ue048Freaku'
|
||||||
chars = [(uwu(ba.SpecialChar.TICKET),
|
chars = [(uwu(babase.SpecialChar.TICKET),
|
||||||
uwu(ba.SpecialChar.CROWN),
|
uwu(babase.SpecialChar.CROWN),
|
||||||
uwu(ba.SpecialChar.DRAGON),
|
uwu(babase.SpecialChar.DRAGON),
|
||||||
uwu(ba.SpecialChar.SKULL),
|
uwu(babase.SpecialChar.SKULL),
|
||||||
uwu(ba.SpecialChar.HEART),
|
uwu(babase.SpecialChar.HEART),
|
||||||
uwu(ba.SpecialChar.FEDORA),
|
uwu(babase.SpecialChar.FEDORA),
|
||||||
uwu(ba.SpecialChar.HAL),
|
uwu(babase.SpecialChar.HAL),
|
||||||
uwu(ba.SpecialChar.YIN_YANG),
|
uwu(babase.SpecialChar.YIN_YANG),
|
||||||
uwu(ba.SpecialChar.EYE_BALL),
|
uwu(babase.SpecialChar.EYE_BALL),
|
||||||
uwu(ba.SpecialChar.HELMET),
|
uwu(babase.SpecialChar.HELMET),
|
||||||
uwu(ba.SpecialChar.OUYA_BUTTON_U)),
|
uwu(babase.SpecialChar.OUYA_BUTTON_U)),
|
||||||
(uwu(ba.SpecialChar.MUSHROOM),
|
(uwu(babase.SpecialChar.MUSHROOM),
|
||||||
uwu(ba.SpecialChar.NINJA_STAR),
|
uwu(babase.SpecialChar.NINJA_STAR),
|
||||||
uwu(ba.SpecialChar.VIKING_HELMET),
|
uwu(babase.SpecialChar.VIKING_HELMET),
|
||||||
uwu(ba.SpecialChar.MOON),
|
uwu(babase.SpecialChar.MOON),
|
||||||
uwu(ba.SpecialChar.SPIDER),
|
uwu(babase.SpecialChar.SPIDER),
|
||||||
uwu(ba.SpecialChar.FIREBALL),
|
uwu(babase.SpecialChar.FIREBALL),
|
||||||
uwu(ba.SpecialChar.MIKIROG),
|
uwu(babase.SpecialChar.MIKIROG),
|
||||||
uwu(ba.SpecialChar.OUYA_BUTTON_O),
|
uwu(babase.SpecialChar.OUYA_BUTTON_O),
|
||||||
uwu(ba.SpecialChar.LOCAL_ACCOUNT),
|
uwu(babase.SpecialChar.LOCAL_ACCOUNT),
|
||||||
uwu(ba.SpecialChar.LOGO)),
|
uwu(babase.SpecialChar.LOGO)),
|
||||||
(uwu(ba.SpecialChar.TICKET),
|
(uwu(babase.SpecialChar.TICKET),
|
||||||
uwu(ba.SpecialChar.FLAG_INDIA),
|
uwu(babase.SpecialChar.FLAG_INDIA),
|
||||||
uwu(ba.SpecialChar.OCULUS_LOGO),
|
uwu(babase.SpecialChar.OCULUS_LOGO),
|
||||||
uwu(ba.SpecialChar.STEAM_LOGO),
|
uwu(babase.SpecialChar.STEAM_LOGO),
|
||||||
uwu(ba.SpecialChar.NVIDIA_LOGO),
|
uwu(babase.SpecialChar.NVIDIA_LOGO),
|
||||||
uwu(ba.SpecialChar.GAME_CENTER_LOGO),
|
uwu(babase.SpecialChar.GAME_CENTER_LOGO),
|
||||||
uwu(ba.SpecialChar.GOOGLE_PLAY_GAMES_LOGO),
|
uwu(babase.SpecialChar.GOOGLE_PLAY_GAMES_LOGO),
|
||||||
uwu(ba.SpecialChar.ALIBABA_LOGO))]
|
uwu(babase.SpecialChar.EXPLODINARY_LOGO))]
|
||||||
nums = []
|
nums = []
|
||||||
pages: Dict[str, Tuple[str, ...]] = {}
|
pages: Dict[str, Tuple[str, ...]] = {}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
# By Freaku / @[Just] Freak#4999
|
# Made by your friend: Freaku
|
||||||
|
|
||||||
|
|
||||||
import ba
|
import babase
|
||||||
from bastd.maps import TowerD
|
import bascenev1 as bs
|
||||||
|
from bascenev1lib.maps import TowerD
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
@ -11,8 +12,8 @@ def new_play_types(cls):
|
||||||
return ['melee', 'keep_away', 'team_flag', 'king_of_the_hill']
|
return ['melee', 'keep_away', 'team_flag', 'king_of_the_hill']
|
||||||
|
|
||||||
|
|
||||||
# ba_meta require api 7
|
# ba_meta require api 8
|
||||||
# ba_meta export plugin
|
# ba_meta export plugin
|
||||||
class byFreaku(ba.Plugin):
|
class byFreaku(babase.Plugin):
|
||||||
def on_app_running(self):
|
def on_app_running(self):
|
||||||
TowerD.get_play_types = new_play_types
|
TowerD.get_play_types = new_play_types
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue