mirror of
https://github.com/imayushsaini/Bombsquad-Ballistica-Modded-Server.git
synced 2026-08-15 13:04:30 +00:00
added more games and maps
This commit is contained in:
parent
d05c5bee29
commit
2f0773c2c9
33 changed files with 8913 additions and 798 deletions
|
|
@ -48,7 +48,7 @@ max_party_size: 6
|
|||
# playlist editor in the regular version of the game.
|
||||
# This will give you a numeric code you can enter here to host that
|
||||
# playlist.
|
||||
playlist_code: 347990
|
||||
playlist_code: 374313
|
||||
|
||||
# Alternately, you can embed playlist data here instead of using codes.
|
||||
# Make sure to set session_type to the correct type for the data here.
|
||||
|
|
|
|||
1
dist/ba_root/.bsuuid
vendored
Normal file
1
dist/ba_root/.bsuuid
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
b6b895e7-a2f9-45f1-b080-25806a8bfca9
|
||||
776
dist/ba_root/config.json
vendored
776
dist/ba_root/config.json
vendored
|
|
@ -1,736 +1,42 @@
|
|||
{
|
||||
"Achievements": {
|
||||
"Boom Goes the Dynamite": {
|
||||
"Complete": false
|
||||
},
|
||||
"Boxer": {
|
||||
"Complete": false
|
||||
},
|
||||
"Dual Wielding": {
|
||||
"Complete": false
|
||||
},
|
||||
"Flawless Victory": {
|
||||
"Complete": false
|
||||
},
|
||||
"Free Loader": {
|
||||
"Complete": false
|
||||
},
|
||||
"Gold Miner": {
|
||||
"Complete": false
|
||||
},
|
||||
"Got the Moves": {
|
||||
"Complete": false
|
||||
},
|
||||
"In Control": {
|
||||
"Complete": false
|
||||
},
|
||||
"Last Stand God": {
|
||||
"Complete": false
|
||||
},
|
||||
"Last Stand Master": {
|
||||
"Complete": false
|
||||
},
|
||||
"Last Stand Wizard": {
|
||||
"Complete": false
|
||||
},
|
||||
"Mine Games": {
|
||||
"Complete": true
|
||||
},
|
||||
"Off You Go Then": {
|
||||
"Complete": true
|
||||
},
|
||||
"Onslaught God": {
|
||||
"Complete": false
|
||||
},
|
||||
"Onslaught Master": {
|
||||
"Complete": false
|
||||
},
|
||||
"Onslaught Training Victory": {
|
||||
"Complete": true
|
||||
},
|
||||
"Onslaught Wizard": {
|
||||
"Complete": false
|
||||
},
|
||||
"Precision Bombing": {
|
||||
"Complete": false
|
||||
},
|
||||
"Pro Boxer": {
|
||||
"Complete": false
|
||||
},
|
||||
"Pro Football Shutout": {
|
||||
"Complete": false
|
||||
},
|
||||
"Pro Football Victory": {
|
||||
"Complete": false
|
||||
},
|
||||
"Pro Onslaught Victory": {
|
||||
"Complete": false
|
||||
},
|
||||
"Pro Runaround Victory": {
|
||||
"Complete": false
|
||||
},
|
||||
"Rookie Football Shutout": {
|
||||
"Complete": false
|
||||
},
|
||||
"Rookie Football Victory": {
|
||||
"Complete": false
|
||||
},
|
||||
"Rookie Onslaught Victory": {
|
||||
"Complete": true
|
||||
},
|
||||
"Runaround God": {
|
||||
"Complete": false
|
||||
},
|
||||
"Runaround Master": {
|
||||
"Complete": false
|
||||
},
|
||||
"Runaround Wizard": {
|
||||
"Complete": false
|
||||
},
|
||||
"Sharing is Caring": {
|
||||
"Complete": false
|
||||
},
|
||||
"Stayin' Alive": {
|
||||
"Complete": false
|
||||
},
|
||||
"Super Mega Punch": {
|
||||
"Complete": false
|
||||
},
|
||||
"Super Punch": {
|
||||
"Complete": true
|
||||
},
|
||||
"TNT Terror": {
|
||||
"Complete": false
|
||||
},
|
||||
"Team Player": {
|
||||
"Complete": true
|
||||
},
|
||||
"The Great Wall": {
|
||||
"Complete": false
|
||||
},
|
||||
"The Wall": {
|
||||
"Complete": false
|
||||
},
|
||||
"Uber Football Shutout": {
|
||||
"Complete": false
|
||||
},
|
||||
"Uber Football Victory": {
|
||||
"Complete": false
|
||||
},
|
||||
"Uber Onslaught Victory": {
|
||||
"Complete": false
|
||||
},
|
||||
"Uber Runaround Victory": {
|
||||
"Complete": false
|
||||
}
|
||||
},
|
||||
"Auto Account State": "Server",
|
||||
"Auto Balance Teams": true,
|
||||
"Bear Coin": 814,
|
||||
"Bear Store": {
|
||||
"Buy Firebombs": false,
|
||||
"Buy Option": false,
|
||||
"Buy Percentage": false,
|
||||
"Promo Code": {
|
||||
"B-0mB3RYT2z": [
|
||||
true,
|
||||
910
|
||||
],
|
||||
"B-Asd14mON9G0D": [
|
||||
true,
|
||||
910
|
||||
],
|
||||
"D-rAcK0cJ23": [
|
||||
true,
|
||||
910
|
||||
],
|
||||
"E-Am54igO42Os": [
|
||||
true,
|
||||
600
|
||||
],
|
||||
"E-M4uN3K34XB": [
|
||||
true,
|
||||
840
|
||||
],
|
||||
"E-a27ZO6f3Y": [
|
||||
true,
|
||||
600
|
||||
],
|
||||
"G-Am54igO42Os": [
|
||||
true,
|
||||
1100
|
||||
],
|
||||
"P-tRo8nM8dZ": [
|
||||
true,
|
||||
2800
|
||||
],
|
||||
"PM-731ClcAF": [
|
||||
true,
|
||||
50000
|
||||
],
|
||||
"Y-tU2B3S": [
|
||||
true,
|
||||
500
|
||||
]
|
||||
}
|
||||
},
|
||||
"Campaigns": {
|
||||
"Easy": {
|
||||
"Onslaught Training": {
|
||||
"Complete": true,
|
||||
"High Scores": {
|
||||
"1 Player": [
|
||||
[
|
||||
286,
|
||||
{
|
||||
"players": [
|
||||
{
|
||||
"character": "Spaz",
|
||||
"name": "smoothie"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
[
|
||||
261,
|
||||
{
|
||||
"players": [
|
||||
{
|
||||
"character": "Spaz",
|
||||
"name": "smoothie"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
[
|
||||
239,
|
||||
{
|
||||
"players": [
|
||||
{
|
||||
"character": "Spaz",
|
||||
"name": "smoothie"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
[
|
||||
49,
|
||||
{
|
||||
"players": [
|
||||
{
|
||||
"character": "Spaz",
|
||||
"name": "smoothie"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
[
|
||||
46,
|
||||
{
|
||||
"players": [
|
||||
{
|
||||
"character": "Spaz",
|
||||
"name": "smoothie"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
[
|
||||
28,
|
||||
{
|
||||
"players": [
|
||||
{
|
||||
"character": "Spaz",
|
||||
"name": "smoothie"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
[
|
||||
5,
|
||||
{
|
||||
"players": [
|
||||
{
|
||||
"character": "Spaz",
|
||||
"name": "smoothie"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
[
|
||||
5,
|
||||
{
|
||||
"players": [
|
||||
{
|
||||
"character": "Spaz",
|
||||
"name": "smoothie"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
[
|
||||
5,
|
||||
{
|
||||
"players": [
|
||||
{
|
||||
"character": "Spaz",
|
||||
"name": "smoothie"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
[
|
||||
5,
|
||||
{
|
||||
"players": [
|
||||
{
|
||||
"character": "Spaz",
|
||||
"name": "smoothie"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Rating": 10.0
|
||||
},
|
||||
"Rookie Onslaught": {
|
||||
"Complete": false,
|
||||
"High Scores": {
|
||||
"1 Player": [
|
||||
[
|
||||
297,
|
||||
{
|
||||
"players": [
|
||||
{
|
||||
"character": "Spaz",
|
||||
"name": "smoothie"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
[
|
||||
34,
|
||||
{
|
||||
"players": [
|
||||
{
|
||||
"character": "Spaz",
|
||||
"name": "smoothie"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Rating": 10.0
|
||||
}
|
||||
}
|
||||
},
|
||||
"Custom Team Colors": [
|
||||
[
|
||||
2.0,
|
||||
0.25,
|
||||
1.0
|
||||
],
|
||||
[
|
||||
1.0,
|
||||
0.25,
|
||||
0.2
|
||||
]
|
||||
],
|
||||
"Custom Team Names": [
|
||||
"ladoo",
|
||||
"barfi"
|
||||
],
|
||||
"Default Player Profiles": {
|
||||
"Client Input Device #1": "_random",
|
||||
"Client Input Device #2": "__account__"
|
||||
},
|
||||
"Free-for-All Playlist Randomize": true,
|
||||
"Free-for-All Playlist Selection": "__default__",
|
||||
"Free-for-All Playlists": {
|
||||
"Just Death Match": [
|
||||
{
|
||||
"settings": {
|
||||
"Epic Mode": false,
|
||||
"Kills to Win Per Player": 10,
|
||||
"Respawn Times": 1.0,
|
||||
"Time Limit": 300,
|
||||
"map": "Doom Shroom"
|
||||
},
|
||||
"type": "bs_death_match.DeathMatchGame"
|
||||
},
|
||||
{
|
||||
"settings": {
|
||||
"Epic Mode": false,
|
||||
"Kills to Win Per Player": 10,
|
||||
"Respawn Times": 1.0,
|
||||
"Time Limit": 300,
|
||||
"map": "Crag Castle"
|
||||
},
|
||||
"type": "bs_death_match.DeathMatchGame"
|
||||
}
|
||||
],
|
||||
"My Free-for-All Playlist": [
|
||||
{
|
||||
"settings": {
|
||||
"Allow Negative Scores": false,
|
||||
"Epic Mode": false,
|
||||
"Kills to Win Per Player": 5,
|
||||
"Respawn Times": 1.0,
|
||||
"Time Limit": 0,
|
||||
"map": "Courtyard"
|
||||
},
|
||||
"type": "bastd.game.deathmatch.DeathMatchGame"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Idle Exit Minutes": null,
|
||||
"Local Account Name": "Server3258837",
|
||||
"PPM Settings": {
|
||||
"Healing Damage PTG": 72,
|
||||
"Powers Gravity": true,
|
||||
"Powerup Name": true,
|
||||
"Powerup Scale": 1.0,
|
||||
"Powerup Style": "Auto",
|
||||
"Powerup Time": false,
|
||||
"Powerup With Shield": true,
|
||||
"Powerups": {
|
||||
"Curse": 1,
|
||||
"Fire Bombs": 3,
|
||||
"Fly Bombs": 3,
|
||||
"Goodbye": 2,
|
||||
"Healing Damage": 1,
|
||||
"Health": 1,
|
||||
"Ice Bombs": 3,
|
||||
"Ice Man": 1,
|
||||
"Impact Bombs": 3,
|
||||
"Impairment Bombs": 2,
|
||||
"Mine Bombs": 2,
|
||||
"Punch": 3,
|
||||
"Shield": 2,
|
||||
"Speed": 2,
|
||||
"Sticky Bombs": 3,
|
||||
"Tank Shield": 1,
|
||||
"Triple": 3
|
||||
},
|
||||
"Tank Shield PTG": 96
|
||||
},
|
||||
"Player Profiles": {
|
||||
"__account__": {
|
||||
"character": "Spaz",
|
||||
"color": [
|
||||
0.5,
|
||||
0.25,
|
||||
1.0
|
||||
],
|
||||
"highlight": [
|
||||
0.5,
|
||||
0.25,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
},
|
||||
"Plugins": {
|
||||
"plugins.Init": {
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"Port": 43210,
|
||||
"Region Pings": {
|
||||
"af-south-1": 328.2357999996748,
|
||||
"ap-northeast-1": 150.0941541948123,
|
||||
"ap-northeast-2": 160.2201884064998,
|
||||
"ap-south-1": 45.05286179925315,
|
||||
"ap-southeast-1": 101.91129060697858,
|
||||
"ap-southeast-2": 183.6228000029223,
|
||||
"ca-central-1": 262.4569968022115,
|
||||
"eu-central-1": 155.88790780561976,
|
||||
"eu-north-1": 181.94498299446423,
|
||||
"eu-south-1": 156.48616400256287,
|
||||
"eu-west-1": 179.42955539320246,
|
||||
"eu-west-2": 158.43393659518915,
|
||||
"eu-west-3": 170.620519401622,
|
||||
"me-south-1": 78.16982959693996,
|
||||
"sa-east-1": 345.57150000182446,
|
||||
"us-east-1": 238.92560360513744,
|
||||
"us-east-2": 257.30932620124076,
|
||||
"us-west-1": 255.34800000605173,
|
||||
"us-west-2": 292.9734999925131
|
||||
},
|
||||
"Selected Coop Game": "Easy:Rookie Onslaught",
|
||||
"Show Tutorial": false,
|
||||
"Signed In Last Session": false,
|
||||
"Team Game Max Player": 25,
|
||||
"Team Game Max Players": 25,
|
||||
"Free-for-All Max Players":25,
|
||||
"Team Tournament Playlist Randomize": true,
|
||||
"Team Tournament Playlist Selection": "My Teams Playlist",
|
||||
"Team Tournament Playlists": {
|
||||
"My Teams Playlist": [
|
||||
{
|
||||
"settings": {
|
||||
"Epic Mode": false,
|
||||
"Kills to Win Per Player": 1,
|
||||
"Respawn Times": 1.0,
|
||||
"Time Limit": 0,
|
||||
"map": "Doom Shroom"
|
||||
},
|
||||
"type": "bastd.game.deathmatch.DeathMatchGame"
|
||||
}
|
||||
],
|
||||
"My Teams Playlist 2": [
|
||||
{
|
||||
"settings": {
|
||||
"Epic Mode": false,
|
||||
"Kills to Win Per Player": 5,
|
||||
"Respawn Times": 1.0,
|
||||
"Time Limit": 0,
|
||||
"map": "Happy Thoughts"
|
||||
},
|
||||
"type": "bastd.game.deathmatch.DeathMatchGame"
|
||||
}
|
||||
],
|
||||
"\u041a\u043e\u043f\u0438\u044f \u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043f\u043b\u0435\u0439-\u043b\u0438\u0441\u0442 \u0440\u0435\u0436\u0438\u043c\u0430 \u041a\u043e\u043c\u0430\u043d\u0434\u044b": [
|
||||
{
|
||||
"settings": {
|
||||
"Epic Mode": false,
|
||||
"Flag Idle Return Time": 30,
|
||||
"Flag Touch Return Time": 0,
|
||||
"Respawn Times": 1.0,
|
||||
"Score to Win": 3,
|
||||
"Time Limit": 600,
|
||||
"map": "Bridgit"
|
||||
},
|
||||
"type": "bsCaptureTheFlag.CTFGame"
|
||||
},
|
||||
{
|
||||
"settings": {
|
||||
"Epic Mode": false,
|
||||
"Respawn Times": 1.0,
|
||||
"Score to Win": 3,
|
||||
"Time Limit": 600,
|
||||
"map": "Step Right Up"
|
||||
},
|
||||
"type": "bsAssault.AssaultGame"
|
||||
},
|
||||
{
|
||||
"settings": {
|
||||
"Balance Total Lives": false,
|
||||
"Epic Mode": false,
|
||||
"Lives Per Player": 3,
|
||||
"Respawn Times": 1.0,
|
||||
"Solo Mode": true,
|
||||
"Time Limit": 600,
|
||||
"map": "Rampage"
|
||||
},
|
||||
"type": "bsElimination.EliminationGame"
|
||||
},
|
||||
{
|
||||
"settings": {
|
||||
"Epic Mode": false,
|
||||
"Kills to Win Per Player": 5,
|
||||
"Respawn Times": 1.0,
|
||||
"Time Limit": 300,
|
||||
"map": "Roundabout"
|
||||
},
|
||||
"type": "bsDeathMatch.DeathMatchGame"
|
||||
},
|
||||
{
|
||||
"settings": {
|
||||
"Respawn Times": 1.0,
|
||||
"Score to Win": 1,
|
||||
"Time Limit": 600,
|
||||
"map": "Hockey Stadium"
|
||||
},
|
||||
"type": "bsHockey.HockeyGame"
|
||||
},
|
||||
{
|
||||
"settings": {
|
||||
"Hold Time": 30,
|
||||
"Respawn Times": 1.0,
|
||||
"Time Limit": 300,
|
||||
"map": "Monkey Face"
|
||||
},
|
||||
"type": "bsKeepAway.KeepAwayGame"
|
||||
},
|
||||
{
|
||||
"settings": {
|
||||
"Balance Total Lives": false,
|
||||
"Epic Mode": true,
|
||||
"Lives Per Player": 1,
|
||||
"Respawn Times": 1.0,
|
||||
"Solo Mode": false,
|
||||
"Time Limit": 120,
|
||||
"map": "Tip Top"
|
||||
},
|
||||
"type": "bsElimination.EliminationGame"
|
||||
},
|
||||
{
|
||||
"settings": {
|
||||
"Epic Mode": false,
|
||||
"Respawn Times": 1.0,
|
||||
"Score to Win": 3,
|
||||
"Time Limit": 300,
|
||||
"map": "Crag Castle"
|
||||
},
|
||||
"type": "bsAssault.AssaultGame"
|
||||
},
|
||||
{
|
||||
"settings": {
|
||||
"Epic Mode": false,
|
||||
"Kills to Win Per Player": 5,
|
||||
"Respawn Times": 1.0,
|
||||
"Time Limit": 300,
|
||||
"map": "Doom Shroom"
|
||||
},
|
||||
"type": "bsDeathMatch.DeathMatchGame"
|
||||
},
|
||||
{
|
||||
"settings": {
|
||||
"Epic Mode": false,
|
||||
"map": "Rampage"
|
||||
},
|
||||
"type": "bsMeteorShower.MeteorShowerGame"
|
||||
},
|
||||
{
|
||||
"settings": {
|
||||
"Epic Mode": false,
|
||||
"Flag Idle Return Time": 30,
|
||||
"Flag Touch Return Time": 0,
|
||||
"Respawn Times": 1.0,
|
||||
"Score to Win": 2,
|
||||
"Time Limit": 600,
|
||||
"map": "Roundabout"
|
||||
},
|
||||
"type": "bsCaptureTheFlag.CTFGame"
|
||||
},
|
||||
{
|
||||
"settings": {
|
||||
"Respawn Times": 1.0,
|
||||
"Score to Win": 21,
|
||||
"Time Limit": 600,
|
||||
"map": "Football Stadium"
|
||||
},
|
||||
"type": "bsFootball.FootballTeamGame"
|
||||
},
|
||||
{
|
||||
"settings": {
|
||||
"Epic Mode": true,
|
||||
"Respawn Times": 0.25,
|
||||
"Score to Win": 3,
|
||||
"Time Limit": 120,
|
||||
"map": "Bridgit"
|
||||
},
|
||||
"type": "bsAssault.AssaultGame"
|
||||
},
|
||||
{
|
||||
"map": "Doom Shroom",
|
||||
"settings": {
|
||||
"Enable Impact Bombs": 1,
|
||||
"Enable Triple Bombs": false,
|
||||
"Target Count": 2,
|
||||
"map": "Doom Shroom"
|
||||
},
|
||||
"type": "bsTargetPractice.TargetPracticeGame"
|
||||
},
|
||||
{
|
||||
"settings": {
|
||||
"Hold Time": 30,
|
||||
"Respawn Times": 1.0,
|
||||
"Time Limit": 300,
|
||||
"map": "Tip Top"
|
||||
},
|
||||
"type": "bsKingOfTheHill.KingOfTheHillGame"
|
||||
},
|
||||
{
|
||||
"settings": {
|
||||
"Epic Mode": false,
|
||||
"Respawn Times": 1.0,
|
||||
"Score to Win": 2,
|
||||
"Time Limit": 300,
|
||||
"map": "Zigzag"
|
||||
},
|
||||
"type": "bsAssault.AssaultGame"
|
||||
},
|
||||
{
|
||||
"settings": {
|
||||
"Epic Mode": false,
|
||||
"Flag Idle Return Time": 30,
|
||||
"Flag Touch Return Time": 0,
|
||||
"Respawn Times": 1.0,
|
||||
"Score to Win": 3,
|
||||
"Time Limit": 300,
|
||||
"map": "Happy Thoughts"
|
||||
},
|
||||
"type": "bsCaptureTheFlag.CTFGame"
|
||||
},
|
||||
{
|
||||
"settings": {
|
||||
"Bomb Spawning": 1000,
|
||||
"Epic Mode": true,
|
||||
"Laps": 1,
|
||||
"Mine Spawning": 2000,
|
||||
"Time Limit": 300,
|
||||
"map": "Big G"
|
||||
},
|
||||
"type": "bsRace.RaceGame"
|
||||
},
|
||||
{
|
||||
"settings": {
|
||||
"Epic Mode": false,
|
||||
"Kills to Win Per Player": 5,
|
||||
"Respawn Times": 1.0,
|
||||
"Time Limit": 300,
|
||||
"map": "Monkey Face"
|
||||
},
|
||||
"type": "bsDeathMatch.DeathMatchGame"
|
||||
},
|
||||
{
|
||||
"settings": {
|
||||
"Hold Time": 30,
|
||||
"Respawn Times": 1.0,
|
||||
"Time Limit": 300,
|
||||
"map": "Lake Frigid"
|
||||
},
|
||||
"type": "bsKeepAway.KeepAwayGame"
|
||||
},
|
||||
{
|
||||
"settings": {
|
||||
"Epic Mode": false,
|
||||
"Flag Idle Return Time": 30,
|
||||
"Flag Touch Return Time": 3,
|
||||
"Respawn Times": 1.0,
|
||||
"Score to Win": 2,
|
||||
"Time Limit": 300,
|
||||
"map": "Tip Top"
|
||||
},
|
||||
"type": "bsCaptureTheFlag.CTFGame"
|
||||
},
|
||||
{
|
||||
"settings": {
|
||||
"Balance Total Lives": false,
|
||||
"Epic Mode": false,
|
||||
"Lives Per Player": 3,
|
||||
"Respawn Times": 1.0,
|
||||
"Solo Mode": false,
|
||||
"Time Limit": 300,
|
||||
"map": "Crag Castle"
|
||||
},
|
||||
"type": "bsElimination.EliminationGame"
|
||||
},
|
||||
{
|
||||
"settings": {
|
||||
"Epic Mode": true,
|
||||
"Respawn Times": 0.25,
|
||||
"Time Limit": 120,
|
||||
"map": "Zigzag"
|
||||
},
|
||||
"type": "bsConquest.ConquestGame"
|
||||
}
|
||||
]
|
||||
},
|
||||
"launchCount": 252,
|
||||
"lc14173": 1,
|
||||
"lc14292": 1
|
||||
}
|
||||
"Achievements": {},
|
||||
"Auto Account State": "Server",
|
||||
"Auto Balance Teams": true,
|
||||
"Campaigns": {},
|
||||
"Custom Team Colors": [
|
||||
[
|
||||
2.0,
|
||||
0.25,
|
||||
1.0
|
||||
],
|
||||
[
|
||||
1.0,
|
||||
0.25,
|
||||
0.2
|
||||
]
|
||||
],
|
||||
"Custom Team Names": [
|
||||
"ladoo",
|
||||
"barfi"
|
||||
],
|
||||
"Fleet Zone Pings": {
|
||||
"prod": {
|
||||
"ap-northeast-1": 156.68950000008408,
|
||||
"ap-northeast-2": 156.49900000016714,
|
||||
"ap-south-1": 39.8473224001209,
|
||||
"ap-southeast-1": 81.71677339999769,
|
||||
"eu-north-1": 169.96319999998377,
|
||||
"me-south-1": 69.94866120011193
|
||||
}
|
||||
},
|
||||
"Free-for-All Playlists": {},
|
||||
"Idle Exit Minutes": null,
|
||||
"Player Profiles": {},
|
||||
"Port": 43210,
|
||||
"Show Tutorial": false,
|
||||
"Signed In Last Session": false,
|
||||
"Team Tournament Playlists": {},
|
||||
"launchCount": 4,
|
||||
"lc14173": 1,
|
||||
"lc14292": 1
|
||||
}
|
||||
1
dist/ba_root/config.json.prev
vendored
Normal file
1
dist/ba_root/config.json.prev
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"Achievements": {}, "Auto Account State": "Server", "Auto Balance Teams": true, "Campaigns": {}, "Custom Team Colors": [[2.0, 0.25, 1.0], [1.0, 0.25, 0.2]], "Custom Team Names": ["ladoo", "barfi"], "Fleet Zone Pings": {"prod": {"ap-northeast-1": 150.23180000025604, "ap-northeast-2": 165.59890000007726, "ap-south-1": 39.26117700029499, "ap-southeast-1": 84.0365405999919, "eu-north-1": 173.02299999983006, "me-south-1": 78.74480959990251}}, "Free-for-All Playlists": {}, "Idle Exit Minutes": null, "Player Profiles": {}, "Port": 43210, "Show Tutorial": false, "Signed In Last Session": false, "Team Tournament Playlists": {}, "launchCount": 3, "lc14173": 1, "lc14292": 1}
|
||||
193
dist/ba_root/mods/games/ArmsRace.py
vendored
Normal file
193
dist/ba_root/mods/games/ArmsRace.py
vendored
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
#Ported by: Freaku / @[Just] Freak#4999
|
||||
|
||||
#Join BCS:
|
||||
# https://discord.gg/ucyaesh
|
||||
|
||||
|
||||
|
||||
# ba_meta require api 6
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import ba
|
||||
from bastd.actor.playerspaz import PlayerSpaz
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Type, List, Dict, Tuple, Union, Sequence, Optional
|
||||
|
||||
|
||||
|
||||
class State:
|
||||
def __init__(self, bomb=None, grab=False, punch=False, curse=False, required=False, final=False, name=''):
|
||||
self.bomb = bomb
|
||||
self.grab = grab
|
||||
self.punch = punch
|
||||
self.pickup = False
|
||||
self.curse = curse
|
||||
self.required = required or final
|
||||
self.final = final
|
||||
self.name = name
|
||||
self.next = None
|
||||
self.index = None
|
||||
|
||||
def apply(self, spaz):
|
||||
spaz.disconnect_controls_from_player()
|
||||
spaz.connect_controls_to_player(enable_punch=self.punch,
|
||||
enable_bomb=self.bomb,
|
||||
enable_pickup=self.grab)
|
||||
if self.curse:
|
||||
spaz.curse_time = -1
|
||||
spaz.curse()
|
||||
if self.bomb:
|
||||
spaz.bomb_type = self.bomb
|
||||
spaz.set_score_text(self.name)
|
||||
|
||||
def get_setting(self):
|
||||
return (self.name)
|
||||
|
||||
|
||||
states = [ State(bomb='normal', name='Basic Bombs'),
|
||||
State(bomb='ice', name='Frozen Bombs'),
|
||||
State(bomb='sticky', name='Sticky Bombs'),
|
||||
State(bomb='impact', name='Impact Bombs'),
|
||||
State(grab=True, name='Grabbing only'),
|
||||
State(punch=True, name='Punching only'),
|
||||
State(curse=True, name='Cursed', final=True) ]
|
||||
|
||||
class Player(ba.Player['Team']):
|
||||
"""Our player type for this game."""
|
||||
def __init__(self):
|
||||
self.state = None
|
||||
|
||||
|
||||
class Team(ba.Team[Player]):
|
||||
"""Our team type for this game."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.score = 0
|
||||
|
||||
|
||||
# ba_meta export game
|
||||
class ArmsRaceGame(ba.TeamGameActivity[Player, Team]):
|
||||
"""A game type based on acquiring kills."""
|
||||
|
||||
name = 'Arms Race'
|
||||
description = 'Upgrade your weapon by eliminating enemies.\nWin the match by being the first player\nto get a kill while cursed.'
|
||||
|
||||
# Print messages when players die since it matters here.
|
||||
announce_player_deaths = True
|
||||
|
||||
@classmethod
|
||||
def get_available_settings(
|
||||
cls, sessiontype: Type[ba.Session]) -> List[ba.Setting]:
|
||||
settings = [
|
||||
ba.IntChoiceSetting(
|
||||
'Time Limit',
|
||||
choices=[
|
||||
('None', 0),
|
||||
('1 Minute', 60),
|
||||
('2 Minutes', 120),
|
||||
('5 Minutes', 300),
|
||||
('10 Minutes', 600),
|
||||
('20 Minutes', 1200),
|
||||
],
|
||||
default=0,
|
||||
),
|
||||
ba.FloatChoiceSetting(
|
||||
'Respawn Times',
|
||||
choices=[
|
||||
('Shorter', 0.25),
|
||||
('Short', 0.5),
|
||||
('Normal', 1.0),
|
||||
('Long', 2.0),
|
||||
('Longer', 4.0),
|
||||
],
|
||||
default=1.0,
|
||||
),
|
||||
ba.BoolSetting('Epic Mode', default=False)]
|
||||
for state in states:
|
||||
if not state.required:
|
||||
settings.append(ba.BoolSetting(state.get_setting(), default=True))
|
||||
|
||||
return settings
|
||||
|
||||
@classmethod
|
||||
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
|
||||
return (issubclass(sessiontype, ba.DualTeamSession)
|
||||
or issubclass(sessiontype, ba.FreeForAllSession))
|
||||
|
||||
@classmethod
|
||||
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
|
||||
return ba.getmaps('melee')
|
||||
|
||||
def __init__(self, settings: dict):
|
||||
super().__init__(settings)
|
||||
self.states = [s for s in states if settings.get(s.name, True)]
|
||||
for i, state in enumerate(self.states):
|
||||
if i < len(self.states) and not state.final:
|
||||
state.next = self.states[i + 1]
|
||||
state.index = i
|
||||
self._dingsound = ba.getsound('dingSmall')
|
||||
self._epic_mode = bool(settings['Epic Mode'])
|
||||
self._time_limit = float(settings['Time Limit'])
|
||||
|
||||
# Base class overrides.
|
||||
self.slow_motion = self._epic_mode
|
||||
self.default_music = (ba.MusicType.EPIC if self._epic_mode else
|
||||
ba.MusicType.TO_THE_DEATH)
|
||||
|
||||
def get_instance_description(self) -> Union[str, Sequence]:
|
||||
return 'Upgrade your weapon by eliminating enemies.'
|
||||
|
||||
def get_instance_description_short(self) -> Union[str, Sequence]:
|
||||
return 'kill ${ARG1} enemies', len(self.states)
|
||||
|
||||
def on_begin(self) -> None:
|
||||
super().on_begin()
|
||||
self.setup_standard_time_limit(self._time_limit)
|
||||
# self.setup_standard_powerup_drops()
|
||||
|
||||
def on_player_join(self, player):
|
||||
if player.state is None:
|
||||
player.state = self.states[0]
|
||||
self.spawn_player(player)
|
||||
|
||||
# overriding the default character spawning..
|
||||
def spawn_player(self, player):
|
||||
if player.state is None:
|
||||
player.state = self.states[0]
|
||||
super().spawn_player(player)
|
||||
player.state.apply(player.actor)
|
||||
|
||||
def isValidKill(self, m):
|
||||
if m.getkillerplayer(Player) is None:
|
||||
return False
|
||||
|
||||
if m.getkillerplayer(Player).team is m.getplayer(Player).team:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def handlemessage(self, msg: Any) -> Any:
|
||||
|
||||
if isinstance(msg, ba.PlayerDiedMessage):
|
||||
if self.isValidKill(msg):
|
||||
if not msg.getkillerplayer(Player).state.final:
|
||||
msg.getkillerplayer(Player).state = msg.getkillerplayer(Player).state.next
|
||||
msg.getkillerplayer(Player).state.apply(msg.getkillerplayer(Player).actor)
|
||||
else:
|
||||
msg.getkillerplayer(Player).team.score += 1
|
||||
self.end_game()
|
||||
self.respawn_player(msg.getplayer(Player))
|
||||
|
||||
else:
|
||||
return super().handlemessage(msg)
|
||||
return None
|
||||
|
||||
def end_game(self) -> None:
|
||||
results = ba.GameResults()
|
||||
for team in self.teams:
|
||||
results.set_team_score(team, team.score)
|
||||
self.end(results=results)
|
||||
515
dist/ba_root/mods/games/BigBall.py
vendored
Normal file
515
dist/ba_root/mods/games/BigBall.py
vendored
Normal file
|
|
@ -0,0 +1,515 @@
|
|||
#Made by MythB
|
||||
#Ported by: Freaku / @[Just] Freak#4999
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# ba_meta require api 6
|
||||
from __future__ import annotations
|
||||
from typing import TYPE_CHECKING
|
||||
import ba,random
|
||||
from bastd.actor.playerspaz import PlayerSpaz
|
||||
from bastd.actor.scoreboard import Scoreboard
|
||||
from bastd.actor.powerupbox import PowerupBoxFactory
|
||||
from bastd.gameutils import SharedObjects
|
||||
from bastd.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(ba.Actor):
|
||||
def __init__(self,position=(0,2.5,0),color=(1,1,1)):
|
||||
super().__init__()
|
||||
activity = self.getactivity()
|
||||
shared = SharedObjects.get()
|
||||
self.node = ba.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,ba.DieMessage):
|
||||
if self.node.exists():
|
||||
self.node.delete()
|
||||
elif isinstance(m,ba.OutOfBoundsMessage):
|
||||
self.handlemessage(ba.DieMessage())
|
||||
else:
|
||||
super().handlemessage(msg)
|
||||
|
||||
|
||||
class Puck(ba.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 = ba.newnode('prop',
|
||||
delegate=self,
|
||||
attrs={
|
||||
'model': 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,
|
||||
'model_scale': 1,
|
||||
'density': 0.02})
|
||||
ba.animate(self.node, 'model_scale', {0: 0, 0.2: 1.3, 0.26: 1})
|
||||
|
||||
def handlemessage(self, msg: Any) -> Any:
|
||||
if isinstance(msg, ba.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, ba.OutOfBoundsMessage):
|
||||
assert self.node
|
||||
self.node.position = self._spawn_pos
|
||||
|
||||
elif isinstance(msg, ba.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 model scale. Better then tint i think, players and objects more visible
|
||||
class NightMod(ba.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 = ba.newnode("prop",
|
||||
attrs={'model': activity._nightModel,
|
||||
'color_texture': activity._nightTex,
|
||||
'body':'sphere',
|
||||
'reflection':'soft',
|
||||
'body_scale': 0.1,
|
||||
'model_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(ba.Player['Team']):
|
||||
"""Our player type for this game."""
|
||||
|
||||
|
||||
class Team(ba.Team[Player]):
|
||||
"""Our team type for this game."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.score = 0
|
||||
|
||||
|
||||
# ba_meta export game
|
||||
class BBGame(ba.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 = [
|
||||
ba.IntSetting(
|
||||
'Score to Win',
|
||||
min_value=1,
|
||||
default=1,
|
||||
increment=1,
|
||||
),
|
||||
ba.IntChoiceSetting(
|
||||
'Time Limit',
|
||||
choices=[
|
||||
('None', 0),
|
||||
('1 Minute', 60),
|
||||
('2 Minutes', 120),
|
||||
('5 Minutes', 300),
|
||||
('10 Minutes', 600),
|
||||
('20 Minutes', 1200),
|
||||
],
|
||||
default=0,
|
||||
),
|
||||
ba.FloatChoiceSetting(
|
||||
'Respawn Times',
|
||||
choices=[
|
||||
('Shorter', 0.25),
|
||||
('Short', 0.5),
|
||||
('Normal', 1.0),
|
||||
('Long', 2.0),
|
||||
('Longer', 4.0),
|
||||
],
|
||||
default=1.0,
|
||||
),
|
||||
ba.BoolSetting('Epic Mode', True),
|
||||
ba.BoolSetting('Night Mode', False),
|
||||
ba.BoolSetting('Grant Powers on Score', False)
|
||||
]
|
||||
default_music = ba.MusicType.HOCKEY
|
||||
|
||||
@classmethod
|
||||
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
|
||||
return issubclass(sessiontype, ba.DualTeamSession)
|
||||
|
||||
@classmethod
|
||||
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
|
||||
return ['Football Stadium']
|
||||
|
||||
def __init__(self, settings: dict):
|
||||
super().__init__(settings)
|
||||
shared = SharedObjects.get()
|
||||
self._scoreboard = Scoreboard()
|
||||
self._cheer_sound = ba.getsound('cheer')
|
||||
self._chant_sound = ba.getsound('crowdChant')
|
||||
self._foghorn_sound = ba.getsound('foghorn')
|
||||
self._swipsound = ba.getsound('swip')
|
||||
self._whistle_sound = ba.getsound('refWhistle')
|
||||
self._ballModel = ba.getmodel("shield")
|
||||
self._ballTex = ba.gettexture("eggTex1")
|
||||
self._ballSound = ba.getsound("impactMedium2")
|
||||
self._flagKaleTex = ba.gettexture("star")
|
||||
self._kaleSound = ba.getsound("metalHit")
|
||||
self._nightModel = ba.getmodel("shield")
|
||||
self._nightTex = ba.gettexture("black")
|
||||
self._kaleMaterial = ba.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 = ba.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 = ba.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', ba.DieMessage())))
|
||||
self._score_region_material = ba.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[ba.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(enable_tnt = False)
|
||||
self._puck_spawn_pos = self.map.get_flag_position(None)
|
||||
self._flagKalesSpawn()
|
||||
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(
|
||||
ba.NodeActor(
|
||||
ba.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(
|
||||
ba.NodeActor(
|
||||
ba.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()
|
||||
ba.playsound(self._chant_sound)
|
||||
|
||||
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 = ba.newnode("light",
|
||||
attrs={'position':kale1,
|
||||
'radius':0.15,
|
||||
'color':(1.0,1.0,0.7)})
|
||||
|
||||
flash = ba.newnode("light",
|
||||
attrs={'position':kale2,
|
||||
'radius':0.15,
|
||||
'color':(1.0,1.0,0.7)})
|
||||
|
||||
flash = ba.newnode("light",
|
||||
attrs={'position':kale3,
|
||||
'radius':0.15,
|
||||
'color':(0.7,1.0,1.0)})
|
||||
|
||||
flash = ba.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 = ba.getcollision()
|
||||
try:
|
||||
puck = collision.sourcenode.getdelegate(Puck, True)
|
||||
player = collision.opposingnode.getdelegate(PlayerSpaz,
|
||||
True).getplayer(
|
||||
Player, True)
|
||||
except ba.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 = ba.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(ba.PowerupMessage('punch'))
|
||||
except: pass
|
||||
|
||||
# Tell all players to celebrate.
|
||||
for player in team.players:
|
||||
if player.actor:
|
||||
player.actor.handlemessage(ba.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(ba.PowerupMessage('shield'))
|
||||
except: pass
|
||||
|
||||
ba.playsound(self._foghorn_sound)
|
||||
ba.playsound(self._cheer_sound)
|
||||
|
||||
self._puck.scored = True
|
||||
|
||||
# Kill the puck (it'll respawn itself shortly).
|
||||
ba.timer(1.0, self._kill_puck)
|
||||
|
||||
light = ba.newnode('light',
|
||||
attrs={
|
||||
'position': ba.getcollision().position,
|
||||
'height_attenuated': False,
|
||||
'color': (1, 0, 0)
|
||||
})
|
||||
ba.animate(light, 'intensity', {0: 0, 0.5: 1, 1.0: 0}, loop=True)
|
||||
ba.timer(1.0, light.delete)
|
||||
|
||||
ba.cameraflash(duration=10.0)
|
||||
self._update_scoreboard()
|
||||
|
||||
def end_game(self) -> None:
|
||||
results = ba.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, ba.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():
|
||||
ba.timer(3.0, self._spawn_puck)
|
||||
else:
|
||||
super().handlemessage(msg)
|
||||
|
||||
def _flash_puck_spawn(self) -> None:
|
||||
light = ba.newnode('light',
|
||||
attrs={
|
||||
'position': self._puck_spawn_pos,
|
||||
'height_attenuated': False,
|
||||
'color': (1, 0, 0)
|
||||
})
|
||||
ba.animate(light, 'intensity', {0.0: 0, 0.25: 1, 0.5: 0}, loop=True)
|
||||
ba.timer(1.0, light.delete)
|
||||
|
||||
def _spawn_puck(self) -> None:
|
||||
ba.playsound(self._swipsound)
|
||||
ba.playsound(self._whistle_sound)
|
||||
self._flash_puck_spawn()
|
||||
assert self._puck_spawn_pos is not None
|
||||
self._puck = Puck(position=self._puck_spawn_pos)
|
||||
self._puck.light = ba.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')
|
||||
227
dist/ba_root/mods/games/Bounty.py
vendored
Normal file
227
dist/ba_root/mods/games/Bounty.py
vendored
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
# Released under the MIT License. See LICENSE for details.
|
||||
#
|
||||
"""DeathMatch game and support classes."""
|
||||
|
||||
# ba_meta require api 6
|
||||
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import ba
|
||||
from bastd.actor.playerspaz import PlayerSpaz
|
||||
from bastd.actor.scoreboard import Scoreboard
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Union, Sequence, Optional
|
||||
|
||||
|
||||
class Player(ba.Player['Team']):
|
||||
"""Our player type for this game."""
|
||||
|
||||
|
||||
class Team(ba.Team[Player]):
|
||||
"""Our team type for this game."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.score = 0
|
||||
|
||||
|
||||
# ba_meta export game
|
||||
class BountyGame(ba.TeamGameActivity[Player, Team]):
|
||||
"""A game type based on acquiring kills."""
|
||||
|
||||
name = 'Bounty'
|
||||
description = 'Score Maximum Stars To Win'
|
||||
|
||||
# Print messages when players die since it matters here.
|
||||
announce_player_deaths = True
|
||||
|
||||
@classmethod
|
||||
def get_available_settings(
|
||||
cls, sessiontype: type[ba.Session]) -> list[ba.Setting]:
|
||||
settings = [ba.IntChoiceSetting(
|
||||
'Time Limit',
|
||||
choices=[
|
||||
('30 Seconds', 30),
|
||||
('1 Minute', 60),
|
||||
('1½ Minute', 90),
|
||||
('2 Minutes', 120),
|
||||
('5 Minutes', 300),
|
||||
('10 Minutes', 600)],
|
||||
default=120,
|
||||
),
|
||||
ba.FloatChoiceSetting(
|
||||
'Respawn Times',
|
||||
choices=[
|
||||
('Short', 0.5),
|
||||
('Normal', 1.0),
|
||||
('Long', 2.0),
|
||||
('Longer', 4.0),
|
||||
],
|
||||
default=1.0,
|
||||
),
|
||||
ba.BoolSetting('Epic Mode', default=False),
|
||||
]
|
||||
|
||||
# In teams mode, a suicide gives a point to the other team, but in
|
||||
# free-for-all it subtracts from your own score. By default we clamp
|
||||
# this at zero to benefit new players, but pro players might like to
|
||||
# be able to go negative. (to avoid a strategy of just
|
||||
# suiciding until you get a good drop)
|
||||
if issubclass(sessiontype, ba.FreeForAllSession):
|
||||
settings.append(
|
||||
ba.BoolSetting('Allow Negative Scores', default=False))
|
||||
|
||||
return settings
|
||||
|
||||
@classmethod
|
||||
def supports_session_type(cls, sessiontype: type[ba.Session]) -> bool:
|
||||
return (issubclass(sessiontype, ba.DualTeamSession)
|
||||
or issubclass(sessiontype, ba.FreeForAllSession))
|
||||
|
||||
@classmethod
|
||||
def get_supported_maps(cls, sessiontype: type[ba.Session]) -> list[str]:
|
||||
return ba.getmaps('melee')
|
||||
|
||||
def __init__(self, settings: dict):
|
||||
super().__init__(settings)
|
||||
self._scoreboard = Scoreboard()
|
||||
self._score_to_win: Optional[int] = None
|
||||
self._dingsound = ba.getsound('dingSmall')
|
||||
self._epic_mode = bool(settings['Epic Mode'])
|
||||
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 = (ba.MusicType.EPIC if self._epic_mode else
|
||||
ba.MusicType.TO_THE_DEATH)
|
||||
|
||||
def get_instance_description(self) -> Union[str, Sequence]:
|
||||
return 'Collect Stars of your enemies.'
|
||||
|
||||
def get_instance_description_short(self) -> Union[str, Sequence]:
|
||||
return 'Collect Stars of your enemies.'
|
||||
|
||||
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)
|
||||
self.setup_standard_powerup_drops()
|
||||
|
||||
# Base kills needed to win on the size of the largest team.
|
||||
self._update_scoreboard()
|
||||
|
||||
def spawn_player(self, player: Player) -> ba.Actor:
|
||||
|
||||
spaz = self.spawn_player_spaz(player)
|
||||
|
||||
assert spaz.node
|
||||
mathnode = ba.newnode('math',
|
||||
owner=spaz.node,
|
||||
attrs={
|
||||
'input1': (0, 1.4, 0),
|
||||
'operation': 'add'
|
||||
})
|
||||
spaz.node.connectattr('torso_position', mathnode, 'input2')
|
||||
players_star = ba.newnode('text',
|
||||
owner=spaz.node,
|
||||
attrs={
|
||||
'text': '*',
|
||||
'in_world': True,
|
||||
'color': (1, 1, 0.4),
|
||||
'scale': 0.02,
|
||||
'h_align': 'center'
|
||||
})
|
||||
player.tag = players_star
|
||||
mathnode.connectattr('output', players_star, 'position')
|
||||
return spaz
|
||||
|
||||
def _update_stars(self, player: Player) -> None:
|
||||
oldstar = player.tag.text.count("*")
|
||||
if player.is_alive():
|
||||
if oldstar < 3:
|
||||
player.tag.text = "*" * (oldstar + 1)
|
||||
elif oldstar == 3:
|
||||
player.tag.text = "**\n**"
|
||||
elif oldstar == 4:
|
||||
player.tag.text = "**\n***"
|
||||
else:
|
||||
player.tag.text = player.tag.text
|
||||
|
||||
def handlemessage(self, msg: Any) -> Any:
|
||||
|
||||
if isinstance(msg, ba.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
|
||||
|
||||
try:
|
||||
star = player.tag.text.count("*")
|
||||
except:
|
||||
star = 0
|
||||
|
||||
# Handle team-kills.
|
||||
if killer.team is player.team:
|
||||
|
||||
# In free-for-all, killing yourself loses you a point.
|
||||
if isinstance(self.session, ba.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:
|
||||
ba.playsound(self._dingsound)
|
||||
for team in self.teams:
|
||||
if team is not killer.team:
|
||||
team.score += star
|
||||
if not killer == player:
|
||||
self._update_stars(killer)
|
||||
|
||||
# Killing someone on another team nets a kill.
|
||||
else:
|
||||
killer.team.score += star
|
||||
self._update_stars(killer)
|
||||
ba.playsound(self._dingsound)
|
||||
|
||||
# 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("+ 1",
|
||||
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)
|
||||
|
||||
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,
|
||||
None)
|
||||
|
||||
def end_game(self) -> None:
|
||||
results = ba.GameResults()
|
||||
for team in self.teams:
|
||||
results.set_team_score(team, team.score)
|
||||
self.end(results=results)
|
||||
237
dist/ba_root/mods/games/DarkFields.py
vendored
Normal file
237
dist/ba_root/mods/games/DarkFields.py
vendored
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
#Made by Froshlee14
|
||||
#Ported by: Freaku / @[Just] Freak#4999
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# ba_meta require api 6
|
||||
from __future__ import annotations
|
||||
from typing import TYPE_CHECKING
|
||||
import ba,random
|
||||
from bastd.actor.playerspaz import PlayerSpaz
|
||||
from bastd.actor.scoreboard import Scoreboard
|
||||
from bastd.actor.bomb import Bomb
|
||||
from bastd.gameutils import SharedObjects
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Type, List, Dict, Tuple, Union, Sequence, Optional
|
||||
|
||||
|
||||
class Player(ba.Player['Team']):
|
||||
"""Our player type for this game."""
|
||||
|
||||
|
||||
class Team(ba.Team[Player]):
|
||||
"""Our team type for this game."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.score = 0
|
||||
|
||||
|
||||
# ba_meta export game
|
||||
class DFGame(ba.TeamGameActivity[Player, Team]):
|
||||
"""A game type based on acquiring kills."""
|
||||
|
||||
name = 'Dark Fields'
|
||||
description = 'Get to the other side.'
|
||||
|
||||
# Print messages when players die since it matters here.
|
||||
announce_player_deaths = True
|
||||
|
||||
@classmethod
|
||||
def get_available_settings(
|
||||
cls, sessiontype: Type[ba.Session]) -> List[ba.Setting]:
|
||||
settings = [
|
||||
ba.IntSetting(
|
||||
'Score to Win',
|
||||
min_value=1,
|
||||
default=3,
|
||||
increment=1,
|
||||
),
|
||||
ba.IntChoiceSetting(
|
||||
'Time Limit',
|
||||
choices=[
|
||||
('None', 0),
|
||||
('1 Minute', 60),
|
||||
('2 Minutes', 120),
|
||||
('5 Minutes', 300),
|
||||
('10 Minutes', 600),
|
||||
('20 Minutes', 1200),
|
||||
],
|
||||
default=0,
|
||||
),
|
||||
ba.FloatChoiceSetting(
|
||||
'Respawn Times',
|
||||
choices=[
|
||||
('Shorter', 0.25),
|
||||
('Short', 0.5),
|
||||
('Normal', 1.0),
|
||||
('Long', 2.0),
|
||||
('Longer', 4.0),
|
||||
],
|
||||
default=1.0,
|
||||
),
|
||||
ba.BoolSetting('Epic Mode', default=False)
|
||||
]
|
||||
return settings
|
||||
|
||||
@classmethod
|
||||
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
|
||||
return (issubclass(sessiontype, ba.DualTeamSession)
|
||||
or issubclass(sessiontype, ba.FreeForAllSession))
|
||||
|
||||
@classmethod
|
||||
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
|
||||
return ['Football Stadium']
|
||||
|
||||
def __init__(self, settings: dict):
|
||||
super().__init__(settings)
|
||||
shared = SharedObjects.get()
|
||||
self._scoreboard = Scoreboard()
|
||||
self._dingsound = ba.getsound('dingSmall')
|
||||
self._epic_mode = bool(settings['Epic Mode'])
|
||||
self._score_to_win = int(
|
||||
settings['Score to Win'])
|
||||
self._time_limit = float(settings['Time Limit'])
|
||||
|
||||
# Base class overrides.
|
||||
self.slow_motion = self._epic_mode
|
||||
self.default_music = (ba.MusicType.EPIC if self._epic_mode else ba.MusicType.TO_THE_DEATH)
|
||||
self._scoreRegionMaterial = ba.Material()
|
||||
self._scoreRegionMaterial.add_actions(
|
||||
conditions=("they_have_material",shared.player_material),
|
||||
actions=(("modify_part_collision","collide",True),
|
||||
("modify_part_collision","physical",False),
|
||||
("call","at_connect", self._onPlayerScores)))
|
||||
self.first_time = True
|
||||
|
||||
def get_instance_description(self) -> Union[str, Sequence]:
|
||||
return 'Get to the other side ${ARG1} times', self._score_to_win
|
||||
|
||||
def get_instance_description_short(self) -> Union[str, Sequence]:
|
||||
return 'Get to the other side ${ARG1} times', 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()
|
||||
ba.getactivity().globalsnode.tint = (0.5, 0.5, 0.5)
|
||||
a = ba.newnode('locator',attrs={'shape':'box','position':(12,0,.1087926362),'color':(5,5,5),'opacity':1,'draw_beauty':True,'additive':False,'size':[2.0,0.1,11.8]})
|
||||
b = ba.newnode('locator',attrs={'shape':'box','position':(-12,0,.1087926362),'color':(5,5,5),'opacity':1,'draw_beauty':True,'additive':False,'size':[2.0,0.1,11.8]})
|
||||
self.isUpdatingMines = False
|
||||
self._scoreSound = ba.getsound('dingSmall')
|
||||
self.setup_standard_time_limit(self._time_limit)
|
||||
|
||||
self._update_scoreboard()
|
||||
for p in self.players:
|
||||
if p.actor is not None:
|
||||
try:p.actor.disconnect_controls_from_player()
|
||||
except Exception as e: print ('Can\'t connect to player',e)
|
||||
|
||||
self._scoreRegions = []
|
||||
defs = self.map.defs
|
||||
self._scoreRegions.append(ba.NodeActor(ba.newnode('region',
|
||||
attrs={'position':defs.boxes['goal1'][0:3],
|
||||
'scale':defs.boxes['goal1'][6:9],
|
||||
'type': 'box',
|
||||
'materials':[self._scoreRegionMaterial]})))
|
||||
self.mines = []
|
||||
self.spawnMines()
|
||||
ba.timer(2.5,self.start)
|
||||
|
||||
def start(self):
|
||||
ba.timer(random.randrange(3,7),self.doRandomLighting)
|
||||
ba.animate_array(ba.getactivity().globalsnode,'tint',3,{0:(0.5,0.5,0.5),2:(0.2,0.2,0.2)})
|
||||
|
||||
def doRandomLighting(self):
|
||||
ba.timer(random.randrange(3,7),self.doRandomLighting)
|
||||
if self.isUpdatingMines: return
|
||||
ba.animate_array(ba.getactivity().globalsnode,'tint',3,{0:(0.5,0.5,0.5),0.8:(0.2,0.2,0.2)})
|
||||
|
||||
def spawnMines(self):
|
||||
delay = 0
|
||||
xs = [10,8,6,4,2,0,-2,-4,-6,-8,-10]
|
||||
for x in xs:
|
||||
for i in range(3):
|
||||
pos = (x,1,random.randrange(-5,6))
|
||||
ba.timer(delay,ba.Call(self.doMine,pos))
|
||||
delay += 0.075
|
||||
ba.timer(2.48,self.stopUpdateMines)
|
||||
|
||||
def stopUpdateMines(self):
|
||||
self.isUpdatingMines = False
|
||||
self.first_time = False
|
||||
|
||||
def updateMines(self):
|
||||
if self.isUpdatingMines: return
|
||||
self.isUpdatingMines = True
|
||||
for m in self.mines:
|
||||
m.node.delete()
|
||||
self.mines = []
|
||||
self.spawnMines()
|
||||
|
||||
def doMine(self,pos):
|
||||
b = Bomb(position=pos,bomb_type='land_mine').autoretain()
|
||||
b.arm()
|
||||
self.mines.append(b)
|
||||
|
||||
# overriding the default character spawning..
|
||||
def spawn_player(self, player: Player):
|
||||
if self.first_time: ba.timer(2.5, ba.Call(self.spawn_with_delay, player))
|
||||
else: self.spawn_with_delay(player)
|
||||
def spawn_with_delay(self, player: Player):
|
||||
spaz = self.spawn_player_spaz(player)
|
||||
position = (-12.4,1,random.randrange(-5,5))
|
||||
spaz.connect_controls_to_player(enable_punch=False,enable_bomb=False)
|
||||
spaz.handlemessage(ba.StandMessage(position, random.uniform(0,360)))
|
||||
return spaz
|
||||
|
||||
def _onPlayerScores(self):
|
||||
try: player = ba.getcollision().opposingnode.getdelegate(PlayerSpaz, True).getplayer(Player, True)
|
||||
except Exception: player = None
|
||||
if player.exists() and player.is_alive():
|
||||
for team in self.teams:
|
||||
if team is player.team:
|
||||
team.score += 1
|
||||
ba.playsound(self._scoreSound)
|
||||
ba.animate_array(ba.getactivity().globalsnode,'tint',3,{0:(0.5,0.5,0.5),2.8:(0.2,0.2,0.2)})
|
||||
self._update_scoreboard()
|
||||
player.actor.handlemessage(ba.DieMessage())
|
||||
self.updateMines()
|
||||
|
||||
def handlemessage(self, msg: Any) -> Any:
|
||||
|
||||
if isinstance(msg, ba.PlayerDiedMessage):
|
||||
|
||||
# Augment standard behavior.
|
||||
super().handlemessage(msg)
|
||||
|
||||
player = msg.getplayer(Player)
|
||||
self.respawn_player(player)
|
||||
|
||||
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):
|
||||
ba.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 = ba.GameResults()
|
||||
for team in self.teams:
|
||||
results.set_team_score(team, team.score)
|
||||
self.end(results=results)
|
||||
487
dist/ba_root/mods/games/EggGame.py
vendored
Normal file
487
dist/ba_root/mods/games/EggGame.py
vendored
Normal file
|
|
@ -0,0 +1,487 @@
|
|||
# Released under the MIT License. See LICENSE for details.
|
||||
|
||||
"""Egg game and support classes."""
|
||||
# The Egg Game - throw egg as far as you can
|
||||
# created in BCS (Bombsquad Consultancy Service) - opensource bombsquad mods for all
|
||||
# discord.gg/ucyaesh join now and give your contribution
|
||||
# The Egg game by mr.smoothy
|
||||
# ba_meta require api 6
|
||||
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import ba
|
||||
from bastd.actor.playerspaz import PlayerSpaz
|
||||
from bastd.actor.scoreboard import Scoreboard
|
||||
from bastd.actor.powerupbox import PowerupBoxFactory
|
||||
from bastd.gameutils import SharedObjects
|
||||
from bastd.actor.flag import Flag
|
||||
import math
|
||||
import random
|
||||
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
|
||||
|
||||
|
||||
class Puck(ba.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 =None
|
||||
self.scored = False
|
||||
self.egg_model = ba.getmodel('egg')
|
||||
self.egg_tex_1 = ba.gettexture('eggTex1')
|
||||
self.egg_tex_2 = ba.gettexture('eggTex2')
|
||||
self.egg_tex_3 = ba.gettexture('eggTex3')
|
||||
self.eggtx=[self.egg_tex_1,self.egg_tex_2,self.egg_tex_3]
|
||||
regg=random.randrange(0,3)
|
||||
assert activity is not None
|
||||
assert isinstance(activity, EggGame)
|
||||
pmats = [shared.object_material, activity.puck_material]
|
||||
self.node = ba.newnode('prop',
|
||||
delegate=self,
|
||||
attrs={
|
||||
'model': self.egg_model,
|
||||
'color_texture': self.eggtx[regg],
|
||||
'body': 'capsule',
|
||||
'reflection': 'soft',
|
||||
'reflection_scale': [0.2],
|
||||
'shadow_size': 0.5,
|
||||
'body_scale':0.7,
|
||||
'is_area_of_interest': True,
|
||||
'position': self._spawn_pos,
|
||||
'materials': pmats
|
||||
})
|
||||
ba.animate(self.node, 'model_scale', {0: 0, 0.2: 0.7, 0.26: 0.6})
|
||||
|
||||
def handlemessage(self, msg: Any) -> Any:
|
||||
if isinstance(msg, ba.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, ba.OutOfBoundsMessage):
|
||||
assert self.node
|
||||
self.node.position = self._spawn_pos
|
||||
|
||||
elif isinstance(msg, ba.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
|
||||
else:
|
||||
super().handlemessage(msg)
|
||||
|
||||
|
||||
class Player(ba.Player['Team']):
|
||||
"""Our player type for this game."""
|
||||
|
||||
|
||||
class Team(ba.Team[Player]):
|
||||
"""Our team type for this game."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.score = 0
|
||||
|
||||
|
||||
# ba_meta export game
|
||||
class EggGame(ba.TeamGameActivity[Player, Team]):
|
||||
"""Egg game."""
|
||||
|
||||
name = 'Epic Egg Game'
|
||||
description = 'Score some goals.'
|
||||
available_settings = [
|
||||
ba.IntSetting(
|
||||
'Score to Win',
|
||||
min_value=1,
|
||||
default=1,
|
||||
increment=1,
|
||||
),
|
||||
ba.IntChoiceSetting(
|
||||
'Time Limit',
|
||||
choices=[
|
||||
('None', 0),
|
||||
('40 Seconds', 40),
|
||||
('1 Minute', 60),
|
||||
('2 Minutes', 120),
|
||||
('5 Minutes', 300),
|
||||
('10 Minutes', 600),
|
||||
('20 Minutes', 1200),
|
||||
],
|
||||
default=0,
|
||||
),
|
||||
ba.FloatChoiceSetting(
|
||||
'Respawn Times',
|
||||
choices=[
|
||||
('Shorter', 0.1),
|
||||
('Short', 0.5),
|
||||
('Normal', 1.0),
|
||||
('Long', 2.0),
|
||||
('Longer', 4.0),
|
||||
],
|
||||
default=1.0,
|
||||
),
|
||||
]
|
||||
default_music = ba.MusicType.HOCKEY
|
||||
|
||||
@classmethod
|
||||
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
|
||||
return issubclass(sessiontype, ba.DualTeamSession)
|
||||
|
||||
@classmethod
|
||||
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
|
||||
return ba.getmaps('football')
|
||||
|
||||
def __init__(self, settings: dict):
|
||||
super().__init__(settings)
|
||||
shared = SharedObjects.get()
|
||||
self.slow_motion = True
|
||||
self._scoreboard = Scoreboard()
|
||||
self._cheer_sound = ba.getsound('cheer')
|
||||
self._chant_sound = ba.getsound('crowdChant')
|
||||
self._foghorn_sound = ba.getsound('foghorn')
|
||||
self._swipsound = ba.getsound('swip')
|
||||
self._whistle_sound = ba.getsound('refWhistle')
|
||||
self.puck_model = ba.getmodel('bomb')
|
||||
self.puck_tex = ba.gettexture('landMine')
|
||||
self.puck_scored_tex = ba.gettexture('landMineLit')
|
||||
self._puck_sound = ba.getsound('metalHit')
|
||||
self.puck_material = ba.Material()
|
||||
self._fake_wall_material=ba.Material()
|
||||
self.HIGHEST=0
|
||||
self._fake_wall_material.add_actions(
|
||||
conditions=('they_have_material', shared.player_material),
|
||||
actions=(
|
||||
('modify_part_collision', 'collide', True),
|
||||
('modify_part_collision', 'physical', True)
|
||||
|
||||
))
|
||||
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', ba.DieMessage())))
|
||||
# self.puck_material.add_actions(
|
||||
# conditions=('they_have_material',shared.footing_material)
|
||||
# actions=(('modify_part_collision', 'collide',
|
||||
# True), ('modify_part_collision', 'physical', True),
|
||||
# ('call', 'at_connect', self._handle_egg_collision))
|
||||
# )
|
||||
self._score_region_material = ba.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.main_ground_material= ba.Material()
|
||||
|
||||
self.main_ground_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_egg_collision)))
|
||||
|
||||
self._puck_spawn_pos: Optional[Sequence[float]] = None
|
||||
self._score_regions: Optional[List[ba.NodeActor]] = None
|
||||
self._puck: Optional[Puck] = None
|
||||
self._pucks=[]
|
||||
self._score_to_win = int(settings['Score to Win'])
|
||||
self._time_limit = float(settings['Time Limit'])
|
||||
|
||||
def get_instance_description(self) -> Union[str, Sequence]:
|
||||
return "Throw Egg as far u can"
|
||||
|
||||
def get_instance_description_short(self) -> Union[str, Sequence]:
|
||||
return "Throw Egg as far u can"
|
||||
|
||||
def on_begin(self) -> None:
|
||||
super().on_begin()
|
||||
if self._time_limit==0.0:
|
||||
self._time_limit=60
|
||||
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()
|
||||
self._spawn_puck()
|
||||
self._spawn_puck()
|
||||
self._spawn_puck()
|
||||
self._spawn_puck()
|
||||
|
||||
# Set up the two score regions.
|
||||
defs = self.map.defs
|
||||
self._score_regions = []
|
||||
pos=(11.88630542755127, 0.3009839951992035, 1.33331298828125)
|
||||
# mat=ba.Material()
|
||||
# mat.add_actions(
|
||||
|
||||
# actions=( ('modify_part_collision','physical',True),
|
||||
# ('modify_part_collision','collide',True))
|
||||
# )
|
||||
# self._score_regions.append(
|
||||
# ba.NodeActor(
|
||||
# ba.newnode('region',
|
||||
# attrs={
|
||||
# 'position': pos,
|
||||
# 'scale': (2,3,5),
|
||||
# 'type': 'box',
|
||||
# 'materials': [self._score_region_material]
|
||||
# })))
|
||||
# pos=(-11.88630542755127, 0.3009839951992035, 1.33331298828125)
|
||||
# self._score_regions.append(
|
||||
# ba.NodeActor(
|
||||
# ba.newnode('region',
|
||||
# attrs={
|
||||
# 'position': pos,
|
||||
# 'scale': (2,3,5),
|
||||
# 'type': 'box',
|
||||
# 'materials': [self._score_region_material]
|
||||
# })))
|
||||
self._score_regions.append(
|
||||
ba.NodeActor(
|
||||
ba.newnode('region',
|
||||
attrs={
|
||||
'position': (-9.21,defs.boxes['goal2'][0:3][1],defs.boxes['goal2'][0:3][2]),
|
||||
'scale': defs.boxes['goal2'][6:9],
|
||||
'type': 'box',
|
||||
'materials': (self._fake_wall_material, )
|
||||
})))
|
||||
pos=(0,0.1,-5)
|
||||
self.main_ground=ba.newnode('region',attrs={'position': pos,'scale': (25,0.001,22),'type': 'box','materials': [self.main_ground_material]})
|
||||
self._update_scoreboard()
|
||||
ba.playsound(self._chant_sound)
|
||||
|
||||
def on_team_join(self, team: Team) -> None:
|
||||
self._update_scoreboard()
|
||||
|
||||
def _handle_puck_player_collide(self) -> None:
|
||||
collision = ba.getcollision()
|
||||
try:
|
||||
puck = collision.sourcenode.getdelegate(Puck, True)
|
||||
player = collision.opposingnode.getdelegate(PlayerSpaz,
|
||||
True).getplayer(
|
||||
Player, True)
|
||||
except ba.NotFoundError:
|
||||
return
|
||||
|
||||
puck.last_players_to_touch = player
|
||||
|
||||
def _kill_puck(self) -> None:
|
||||
self._puck = None
|
||||
def _handle_egg_collision(self) -> None:
|
||||
|
||||
no=ba.getcollision().opposingnode
|
||||
pos=no.position
|
||||
egg=no.getdelegate(Puck)
|
||||
source_player=egg.last_players_to_touch
|
||||
if source_player==None or pos[0]< -8 or not source_player.node.exists() :
|
||||
return
|
||||
|
||||
|
||||
try:
|
||||
col=source_player.team.color
|
||||
self.flagg=Flag(pos,touchable=False,color=col).autoretain()
|
||||
self.flagg.is_area_of_interest=True
|
||||
player_pos=source_player.node.position
|
||||
|
||||
distance = math.sqrt( pow(player_pos[0]-pos[0],2) + pow(player_pos[2]-pos[2],2))
|
||||
|
||||
|
||||
dis_mark=ba.newnode('text',
|
||||
|
||||
attrs={
|
||||
'text':str(round(distance,2))+"m",
|
||||
'in_world':True,
|
||||
'scale':0.02,
|
||||
'h_align':'center',
|
||||
'position':(pos[0],1.6,pos[2]),
|
||||
'color':col
|
||||
})
|
||||
ba.animate(dis_mark,'scale',{
|
||||
0.0:0, 0.5:0.01
|
||||
})
|
||||
if distance > self.HIGHEST:
|
||||
self.HIGHEST=distance
|
||||
self.stats.player_scored(
|
||||
source_player,
|
||||
10,
|
||||
big_message=False)
|
||||
|
||||
no.delete()
|
||||
ba.timer(2,self._spawn_puck)
|
||||
source_player.team.score=int(distance)
|
||||
|
||||
except():
|
||||
pass
|
||||
def spawn_player(self, player: Player) -> ba.Actor:
|
||||
|
||||
|
||||
zoo=random.randrange(-4,5)
|
||||
pos=(-11.204887390136719, 0.2998693287372589, zoo)
|
||||
spaz = self.spawn_player_spaz(
|
||||
player, position=pos, angle=90 )
|
||||
assert spaz.node
|
||||
|
||||
# Prevent controlling of characters before the start of the race.
|
||||
|
||||
return spaz
|
||||
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 = ba.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 all players to celebrate.
|
||||
for player in team.players:
|
||||
if player.actor:
|
||||
player.actor.handlemessage(ba.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],
|
||||
20,
|
||||
big_message=True)
|
||||
|
||||
# End game if we won.
|
||||
if team.score >= self._score_to_win:
|
||||
self.end_game()
|
||||
|
||||
ba.playsound(self._foghorn_sound)
|
||||
ba.playsound(self._cheer_sound)
|
||||
|
||||
# self._puck.scored = True
|
||||
|
||||
# Change puck texture to something cool
|
||||
# self._puck.node.color_texture = self.puck_scored_tex
|
||||
# Kill the puck (it'll respawn itself shortly).
|
||||
ba.timer(1.0, self._kill_puck)
|
||||
|
||||
# light = ba.newnode('light',
|
||||
# attrs={
|
||||
# 'position': ba.getcollision().position,
|
||||
# 'height_attenuated': False,
|
||||
# 'color': (1, 0, 0)
|
||||
# })
|
||||
# ba.animate(light, 'intensity', {0: 0, 0.5: 1, 1.0: 0}, loop=True)
|
||||
# ba.timer(1.0, light.delete)
|
||||
|
||||
ba.cameraflash(duration=10.0)
|
||||
self._update_scoreboard()
|
||||
|
||||
def end_game(self) -> None:
|
||||
results = ba.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, ba.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():
|
||||
ba.timer(3.0, self._spawn_puck)
|
||||
else:
|
||||
super().handlemessage(msg)
|
||||
|
||||
def _flash_puck_spawn(self) -> None:
|
||||
# light = ba.newnode('light',
|
||||
# attrs={
|
||||
# 'position': self._puck_spawn_pos,
|
||||
# 'height_attenuated': False,
|
||||
# 'color': (1, 0, 0)
|
||||
# })
|
||||
# ba.animate(light, 'intensity', {0.0: 0, 0.25: 1, 0.5: 0}, loop=True)
|
||||
# ba.timer(1.0, light.delete)
|
||||
pass
|
||||
def _spawn_puck(self) -> None:
|
||||
# ba.playsound(self._swipsound)
|
||||
# ba.playsound(self._whistle_sound)
|
||||
self._flash_puck_spawn()
|
||||
assert self._puck_spawn_pos is not None
|
||||
zoo=random.randrange(-5,6)
|
||||
pos=(-11.204887390136719, 0.2998693287372589, zoo)
|
||||
self._pucks.append (Puck(position=pos))
|
||||
293
dist/ba_root/mods/games/GetTheTarget.py
vendored
Normal file
293
dist/ba_root/mods/games/GetTheTarget.py
vendored
Normal file
|
|
@ -0,0 +1,293 @@
|
|||
# Made by Froshlee14
|
||||
# ba_meta require api 6
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import ba, _ba, random
|
||||
from bastd.actor.scoreboard import Scoreboard
|
||||
from bastd.actor.playerspaz import PlayerSpaz
|
||||
from bastd.actor import spaz
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Union, Type, List, Dict, Tuple, Sequence, Optional
|
||||
|
||||
class Player(ba.Player['Team']):
|
||||
"""Our player type for this game."""
|
||||
|
||||
|
||||
class Team(ba.Team[Player]):
|
||||
"""Our team type for this game."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.score = 0
|
||||
|
||||
# ba_meta export game
|
||||
class GetTheTargetGame(ba.TeamGameActivity[Player, Team]):
|
||||
name = 'Get the Target'
|
||||
description = 'Kill target to get points (dont kill if teammate). If you\'re \nthe Target, survive to get points, \nplayer/team that reached the\n required points, wins.'
|
||||
announce_player_deaths = True
|
||||
|
||||
@classmethod
|
||||
def get_available_settings(
|
||||
cls, sessiontype: Type[ba.Session]) -> List[ba.Setting]:
|
||||
settings = [
|
||||
ba.IntSetting("Points to Win Per Player", min_value=1, default=5, increment=1),
|
||||
ba.IntSetting("Time to Kill", min_value=5, max_value=30, default=10, increment=1),
|
||||
ba.IntChoiceSetting("Time Limit", choices=[('None', 0),('1 Minute', 60),('2 Minutes', 120),('5 Minutes', 300),('10 Minutes', 600),('20 Minutes', 1200)],default=0),
|
||||
ba.FloatChoiceSetting("Respawn Times",choices=[('Shorter', 0.25),('Short', 0.5),('Normal', 1.0),('Long', 2.0),('Longer', 4.0)],default=1.0),
|
||||
ba.IntChoiceSetting("Target Indicator", choices=[('None', 0),('Light', 1),('Text', 2)],default=0),
|
||||
ba.BoolSetting("Epic Mode", default=False)
|
||||
]
|
||||
return settings
|
||||
|
||||
@classmethod
|
||||
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
|
||||
return (issubclass(sessiontype, ba.DualTeamSession)
|
||||
or issubclass(sessiontype, ba.FreeForAllSession))
|
||||
|
||||
@classmethod
|
||||
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
|
||||
return ba.getmaps('melee')
|
||||
|
||||
def __init__(self, settings: dict):
|
||||
super().__init__(settings)
|
||||
self.settings = settings
|
||||
if self.settings['Epic Mode']: self.slow_motion = True
|
||||
self._chosed_player = self.chosen_player = None
|
||||
self._score_to_win: Optional[int] = None
|
||||
self._dingsound = ba.getsound('dingSmall')
|
||||
self._chosing_sound = ba.getsound('scoreIncrease')
|
||||
self._chosed_sound = ba.getsound('cashRegister2')
|
||||
self._error_sound = ba.getsound('error')
|
||||
self._tick_sound = ba.getsound('tick')
|
||||
self._time_remaining = int(self.settings['Time to Kill'])
|
||||
self._time_limit = float(settings['Time Limit'])
|
||||
self.ytpe = int(settings["Target Indicator"])
|
||||
self._scoreboard = Scoreboard()
|
||||
|
||||
self.default_music = (ba.MusicType.EPIC if self.slow_motion else
|
||||
ba.MusicType.TO_THE_DEATH)
|
||||
|
||||
def get_instance_description(self) -> Union[str, Sequence]:
|
||||
return 'Kill enemy targets or Survive ${ARG1} times.', self._score_to_win
|
||||
|
||||
def get_instance_scoreboard_display_string(self) -> str:
|
||||
return 'Kill target/Survive ' + str(self._score_to_win) + ' times.'
|
||||
|
||||
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)
|
||||
self.setup_standard_powerup_drops()
|
||||
self._score_to_win = (int(self.settings["Points to Win Per Player"]) *
|
||||
max(1, max(len(t.players) for t in self.teams)))
|
||||
self._update_scoreboard()
|
||||
ba.timer(3000 * 0.001, self.star_chosing_player)
|
||||
|
||||
self._chose_text = ba.newnode('text',
|
||||
attrs={
|
||||
'text':' ',
|
||||
'v_attach':'bottom',
|
||||
'h_attach':'center',
|
||||
'h_align':'center',
|
||||
'v_align':'center',
|
||||
'maxwidth':150,
|
||||
'shadow':1.0,
|
||||
'flatness':1.0,
|
||||
'color':(1,1,1),
|
||||
'scale':1,
|
||||
'position':(0,155)})
|
||||
|
||||
def on_player_leave(self, player: PlayerType) -> None:
|
||||
super().on_player_leave(player)
|
||||
if len(self.players) in [0,1]: self.end_game()
|
||||
if player == self._chosed_player: self.star_chosing_player()
|
||||
|
||||
def print_random_icon(self) -> None:
|
||||
get_alive = []
|
||||
for spas in self.players:
|
||||
if spas.is_alive():
|
||||
get_alive.append(spas)
|
||||
|
||||
if not len(get_alive) == 0:
|
||||
self._chose_text.text = 'Chosing Player...'
|
||||
self.loops += 1
|
||||
player = random.choice(get_alive)
|
||||
icon = player.get_icon()
|
||||
outline_tex = ba.gettexture('characterIconMask')
|
||||
texture = icon['texture']
|
||||
self._image = ba.NodeActor(ba.newnode('image',
|
||||
attrs={'texture':texture,
|
||||
'tint_texture':icon['tint_texture'],
|
||||
'tint_color':icon['tint_color'],
|
||||
'tint2_color':icon['tint2_color'],
|
||||
'mask_texture':outline_tex,
|
||||
'position':(0,80),
|
||||
'scale':(100,100), 'opacity':1.0,
|
||||
'absolute_scale':True,'attach':'bottomCenter'}))
|
||||
self._name = ba.NodeActor(ba.newnode('text',
|
||||
attrs={'v_attach':'bottom', 'h_attach':'center',
|
||||
'text':ba.Lstr(value=player.getname()),
|
||||
'maxwidth':100, 'h_align':'center',
|
||||
'v_align':'center', 'shadow':1.0,
|
||||
'flatness':1.0, 'color':ba.safecolor(icon['tint_color']),
|
||||
'scale':1,'position':(0,20)}))
|
||||
if self.loops >= self.loop_max:
|
||||
self.chosen_player = player
|
||||
self.stopn_chose_player()
|
||||
else:
|
||||
self._chose_text.text = 'Waiting for players...'
|
||||
texture = ba.gettexture("powerupCurse")
|
||||
self._image = ba.NodeActor(ba.newnode('image',
|
||||
attrs={'texture':texture,
|
||||
'position':(0,80),
|
||||
'scale':(100,100), 'opacity':1.0,
|
||||
'absolute_scale':True,'attach':'bottomCenter'}))
|
||||
self._name = ba.NodeActor(ba.newnode('text',
|
||||
attrs={'v_attach':'bottom', 'h_attach':'center',
|
||||
'text':" ",
|
||||
'maxwidth':100, 'h_align':'center',
|
||||
'v_align':'center', 'shadow':1.0,
|
||||
'flatness':1.0,
|
||||
'color':(1,1,1),
|
||||
'scale':1,'position':(0,20)}))
|
||||
return
|
||||
|
||||
|
||||
def star_chosing_player(self) -> None:
|
||||
if len(self.players) in [0,1]: self.end_game()
|
||||
self._sound = ba.NodeActor(ba.newnode('sound',attrs={'sound':self._chosing_sound,'volume':1.0}))
|
||||
self.stop_timer()
|
||||
self.loops = 0
|
||||
self.loop_max = random.randrange(15,30)
|
||||
self._chosed_player = None
|
||||
self._logo_effect = ba.Timer(80 * 0.001,ba.WeakCall(self.print_random_icon),repeat=True)
|
||||
self._chose_text.color = (1,1,1)
|
||||
|
||||
def stopn_chose_player(self) -> None:
|
||||
self._sound = None
|
||||
self._logo_effect = None
|
||||
ba.playsound(self._chosed_sound)
|
||||
player = self.chosen_player
|
||||
self._chosed_player = player
|
||||
self._chose_text.text = 'Kill the Enemy!'
|
||||
self._chose_text.color = (1,1,0)
|
||||
|
||||
palyer = player.actor
|
||||
if self.ytpe == 1:
|
||||
palyer.r = ba.newnode('light',
|
||||
attrs={
|
||||
'radius':0.2,
|
||||
'intensity': 5.0,
|
||||
'color': palyer.node.color
|
||||
})
|
||||
palyer.node.connectattr('position', palyer.r, 'position')
|
||||
elif self.ytpe == 2:
|
||||
dummy = ba.newnode('math',owner=palyer.node,attrs={'input1': (0, 1.25, 0),'operation': 'add'})
|
||||
palyer.node.connectattr('position', dummy, 'input2')
|
||||
palyer.r = ba.newnode('text',owner=palyer.node,
|
||||
attrs={'text': 'TARGET!',
|
||||
'in_world': True,
|
||||
'shadow': 1.0,
|
||||
'flatness': 1.5,
|
||||
'scale': 0.014,
|
||||
'h_align': 'center',})
|
||||
ba.animate_array(palyer.r,'color',3,{
|
||||
0.0:(0.3, 0.3, 1.0),
|
||||
0.5:(1, 0.3, 0.3),
|
||||
1.0:(0.3, 1 , 0.3),
|
||||
2.0:(0.3, 0.3, 1.0)
|
||||
}, True)
|
||||
dummy.connectattr('output', palyer.r, 'position')
|
||||
self.start_timer()
|
||||
|
||||
def start_timer(self) -> None:
|
||||
self._time_remaining = self.settings['Time to Kill']
|
||||
self._timer_x = ba.Timer(1000*0.001,ba.WeakCall(self.tick),repeat=True)
|
||||
|
||||
def stop_timer(self) -> None:
|
||||
self._time = None
|
||||
self._timer_x = None
|
||||
|
||||
def tick(self) -> None:
|
||||
self.check_for_expire()
|
||||
self._time = ba.NodeActor(ba.newnode('text',
|
||||
attrs={'v_attach':'top', 'h_attach':'center',
|
||||
'text':('Kill Time: '+str(self._time_remaining)+'s'), 'opacity': 0.8,
|
||||
'maxwidth':100, 'h_align':'center',
|
||||
'v_align':'center', 'shadow':1.0,
|
||||
'flatness':1.0, 'color':(1,1,1),
|
||||
'scale':2,'position':(0,-100)}))
|
||||
self._time_remaining -= 1
|
||||
ba.playsound(self._tick_sound)
|
||||
|
||||
def check_for_expire(self) -> None:
|
||||
if self._time_remaining <= 0:
|
||||
self.stop_timer()
|
||||
if len(self.players) == 0: pass
|
||||
elif self._chosed_player.is_alive():
|
||||
player = self._chosed_player
|
||||
player.team.score += 1
|
||||
player.actor.r.delete()
|
||||
ba.playsound(self._dingsound)
|
||||
self._update_scoreboard()
|
||||
if any(team.score >= self._score_to_win for team in self.teams):
|
||||
ba.timer(500*0.001,self.end_game)
|
||||
self._chose_text.text = 'Survived!'
|
||||
self._chose_text.color = (0,1,0)
|
||||
ba.timer(600*0.001,self.star_chosing_player)
|
||||
|
||||
def handlemessage(self, msg: Any) -> Any:
|
||||
if isinstance(msg, ba.PlayerDiedMessage):
|
||||
super().handlemessage(msg)
|
||||
player = msg.getplayer(Player)
|
||||
self.respawn_player(player)
|
||||
|
||||
killer = msg.getkillerplayer(Player)
|
||||
assert self._score_to_win is not None
|
||||
|
||||
if player == self._chosed_player:
|
||||
self._chosed_player.actor.r.delete()
|
||||
if killer.team is player.team:
|
||||
if isinstance(self.session, ba.FreeForAllSession):
|
||||
player.team.score = max(0,player.team.score-1)
|
||||
else:
|
||||
ba.playsound(self._dingsound)
|
||||
for team in self.teams:
|
||||
if team is not killer.team:
|
||||
team.score += 1
|
||||
else:
|
||||
killer.team.score += 1
|
||||
ba.playsound(self._dingsound)
|
||||
try: killer.actor.set_score_text(str(killer.team.score)+'/'+str(self._score_to_win),color=killer.team.color,flash=True)
|
||||
except Exception: pass
|
||||
|
||||
self._update_scoreboard()
|
||||
if any(team.score >= self._score_to_win for team in self.teams):
|
||||
ba.timer(500*0.001,self.end_game)
|
||||
|
||||
if killer != self._chosed_player:
|
||||
self._chose_text.text = 'Killed!'
|
||||
self._chose_text.color = (1,0.5,0)
|
||||
else:
|
||||
self._chose_text.text = 'Dead!'
|
||||
self._chose_text.color = (1.0,0,0)
|
||||
ba.playsound(self._error_sound)
|
||||
ba.timer(600*0.001,self.star_chosing_player)
|
||||
|
||||
else: super().handlemessage(msg)
|
||||
|
||||
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 = ba.GameResults()
|
||||
for team in self.teams:
|
||||
results.set_team_score(team, team.score)
|
||||
self.end(results=results)
|
||||
31
dist/ba_root/mods/games/GravityFalls.py
vendored
Normal file
31
dist/ba_root/mods/games/GravityFalls.py
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
## Made by MattZ45986 on GitHub
|
||||
## Ported by: Freaku / @[Just] Freak#4999
|
||||
|
||||
|
||||
import ba
|
||||
from bastd.game.elimination import EliminationGame
|
||||
|
||||
|
||||
|
||||
# ba_meta require api 6
|
||||
# ba_meta export game
|
||||
class GFGame(EliminationGame):
|
||||
name = 'Gravity Falls'
|
||||
|
||||
def spawn_player(self, player):
|
||||
actor = self.spawn_player_spaz(player, (0,5,0))
|
||||
if not self._solo_mode:
|
||||
ba.timer(0.3, ba.Call(self._print_lives, player))
|
||||
|
||||
# If we have any icons, update their state.
|
||||
for icon in player.icons:
|
||||
icon.handle_player_spawned()
|
||||
ba.timer(1,ba.Call(self.raise_player, player))
|
||||
return actor
|
||||
|
||||
def raise_player(self, player):
|
||||
if player.is_alive():
|
||||
try:
|
||||
player.actor.node.handlemessage("impulse",player.actor.node.position[0],player.actor.node.position[1]+.5,player.actor.node.position[2],0,5,0, 3,10,0,0, 0,5,0)
|
||||
except: pass
|
||||
ba.timer(0.05,ba.Call(self.raise_player,player))
|
||||
676
dist/ba_root/mods/games/Heist.py
vendored
Normal file
676
dist/ba_root/mods/games/Heist.py
vendored
Normal file
|
|
@ -0,0 +1,676 @@
|
|||
# ba_meta require api 6
|
||||
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import ba
|
||||
import _ba
|
||||
import math
|
||||
import random
|
||||
from bastd.actor import spawner
|
||||
from bastd.actor.bomb import BombFactory
|
||||
from bastd.actor.spazfactory import SpazFactory
|
||||
from bastd.gameutils import SharedObjects
|
||||
from bastd.actor.bomb import ExplodeHitMessage
|
||||
from ba._gameutils import show_damage_count
|
||||
from bastd.actor.playerspaz import PlayerSpaz
|
||||
from bastd.actor.powerupbox import PowerupBox
|
||||
from bastd.actor.spazbot import SpazBotSet, ExplodeyBotNoTimeLimit
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Union, Sequence, Optional
|
||||
|
||||
|
||||
class Blast(ba.Actor):
|
||||
|
||||
def __init__(self,
|
||||
position: Sequence[float] = (0.0, 1.0, 0.0),
|
||||
blast_radius: float = 2.0,
|
||||
color: Sequence[float] = (0.0, 1.0, 0.0)):
|
||||
super().__init__()
|
||||
|
||||
shared = SharedObjects.get()
|
||||
factory = BombFactory.get()
|
||||
|
||||
self.radius = blast_radius
|
||||
|
||||
rmats = (factory.blast_material, shared.attack_material)
|
||||
self.node = ba.newnode(
|
||||
'region',
|
||||
delegate=self,
|
||||
attrs={
|
||||
'position': (position[0], position[1] - 0.1, position[2]),
|
||||
'scale': (self.radius, self.radius, self.radius),
|
||||
'type': 'sphere',
|
||||
'materials': rmats
|
||||
},
|
||||
)
|
||||
ba.timer(0.05, self.node.delete)
|
||||
|
||||
explosion = ba.newnode('explosion',
|
||||
attrs={
|
||||
'position': position,
|
||||
'radius': self.radius * 0.8,
|
||||
'color': (color[0] * 0.3,
|
||||
color[1] * 0.3,
|
||||
color[2] * 0.3),
|
||||
'big': True
|
||||
})
|
||||
ba.timer(1.0, explosion.delete)
|
||||
|
||||
light = ba.newnode('light',
|
||||
attrs={
|
||||
'position': position,
|
||||
'volume_intensity_scale': 10.0,
|
||||
'color': (1, 0.3, 0.1)
|
||||
})
|
||||
scl = random.uniform(0.6, 0.9) * 3.0
|
||||
scorch_radius = self.radius * 1.4
|
||||
light_radius = self.radius * 0.6
|
||||
iscale = 0.8
|
||||
ba.animate(
|
||||
light, 'intensity', {
|
||||
0: 2.0 * iscale,
|
||||
scl * 0.02: 0.1 * iscale,
|
||||
scl * 0.025: 0.2 * iscale,
|
||||
scl * 0.05: 17.0 * iscale,
|
||||
scl * 0.06: 5.0 * iscale,
|
||||
scl * 0.08: 4.0 * iscale,
|
||||
scl * 0.2: 0.6 * iscale,
|
||||
scl * 2.0: 0.00 * iscale,
|
||||
scl * 3.0: 0.0
|
||||
})
|
||||
ba.animate(
|
||||
light, 'radius', {
|
||||
0: light_radius * 0.2,
|
||||
scl * 0.05: light_radius * 0.55,
|
||||
scl * 0.1: light_radius * 0.3,
|
||||
scl * 0.3: light_radius * 0.15,
|
||||
scl * 1.0: light_radius * 0.05
|
||||
})
|
||||
ba.timer(scl * 3.0, light.delete)
|
||||
|
||||
scorch = ba.newnode('scorch',
|
||||
attrs={
|
||||
'position': position,
|
||||
'size': scorch_radius * 0.5,
|
||||
'color': (color[0] * 0.6,
|
||||
color[1] * 0.6,
|
||||
color[2] * 0.6),
|
||||
'big': True
|
||||
})
|
||||
ba.animate(scorch, 'presence', {3.000: 1, 13.000: 0})
|
||||
ba.timer(13.0, scorch.delete)
|
||||
|
||||
lpos = light.position
|
||||
ba.playsound(factory.random_explode_sound(), position=lpos)
|
||||
ba.playsound(factory.random_explode_sound(), position=lpos)
|
||||
ba.playsound(factory.debris_fall_sound, position=lpos)
|
||||
ba.camerashake(intensity=5.0)
|
||||
|
||||
def _extra_boom() -> None:
|
||||
ba.playsound(factory.random_explode_sound(), position=lpos)
|
||||
ba.timer(0.25, _extra_boom)
|
||||
|
||||
def _extra_debris_sound() -> None:
|
||||
ba.playsound(factory.debris_fall_sound, position=lpos)
|
||||
ba.playsound(factory.wood_debris_fall_sound, position=lpos)
|
||||
ba.timer(0.4, _extra_debris_sound)
|
||||
|
||||
# ba.emitfx(position=position,
|
||||
# count=100,
|
||||
# scale=1.8,
|
||||
# spread=5,
|
||||
# chunk_type='spark')
|
||||
# ba.emitfx(position=position,
|
||||
# count=100,
|
||||
# spread=5,
|
||||
# scale=2,
|
||||
# chunk_type='ice',
|
||||
# emit_type='stickers')
|
||||
ba.emitfx(position=position,
|
||||
count=1000,
|
||||
spread=500,
|
||||
scale=10,
|
||||
chunk_type='slime')
|
||||
# ba.emitfx(position=position,
|
||||
# count=20,
|
||||
# scale=1,
|
||||
# spread=500,
|
||||
# chunk_type='sweat',
|
||||
# emit_type='tendrils')
|
||||
|
||||
def handlemessage(self, msg: Any) -> Any:
|
||||
assert not self.expired
|
||||
|
||||
if isinstance(msg, ba.DieMessage):
|
||||
if self.node:
|
||||
self.node.delete()
|
||||
|
||||
elif isinstance(msg, ExplodeHitMessage):
|
||||
node = ba.getcollision().opposingnode
|
||||
assert self.node
|
||||
nodepos = self.node.position
|
||||
mag = 2000.0
|
||||
mag *= 2.0
|
||||
|
||||
node.handlemessage(
|
||||
ba.HitMessage(pos=nodepos,
|
||||
velocity=(0, 0, 0),
|
||||
magnitude=mag,
|
||||
hit_type='explosion',
|
||||
hit_subtype='normal',
|
||||
radius=self.radius))
|
||||
else:
|
||||
return super().handlemessage(msg)
|
||||
return None
|
||||
|
||||
|
||||
class TNTBox(ba.Actor):
|
||||
|
||||
def __init__(self,
|
||||
team_id: ba.Team,
|
||||
modeltype: float = None,
|
||||
position: Sequence[float] = None,
|
||||
hitpoints: float = 1000,
|
||||
team: str = None):
|
||||
super().__init__()
|
||||
shared = SharedObjects.get()
|
||||
activity = self.getactivity()
|
||||
spaz = SpazFactory.get()
|
||||
|
||||
self.team = team_id
|
||||
self.modeltype = modeltype
|
||||
self.team_str = team
|
||||
self.teamcolor = team_id.color
|
||||
self.position = position
|
||||
self.hitpoints = hitpoints
|
||||
self.hitpoints_max = hitpoints
|
||||
self._width = 240
|
||||
self._width_max = 240
|
||||
self._height = 35
|
||||
self._bar_width = 240
|
||||
self._bar_height = 35
|
||||
self._bar_tex = self._backing_tex = ba.gettexture('bar')
|
||||
self._cover_tex = ba.gettexture('uiAtlas')
|
||||
self._model = ba.getmodel('meterTransparent')
|
||||
|
||||
if team == 'team 1':
|
||||
self.bar_posx = -200 - 120
|
||||
else:
|
||||
self.bar_posx = 200 - 120
|
||||
|
||||
self.box_material = ba.Material()
|
||||
no_collide_material = ba.Material()
|
||||
self.box_material.add_actions(
|
||||
conditions=('they_have_material', shared.pickup_material),
|
||||
actions=('modify_part_collision', 'collide', False),
|
||||
)
|
||||
|
||||
if modeltype == 1:
|
||||
self.node = ba.newnode(
|
||||
'prop',
|
||||
delegate=self,
|
||||
attrs={
|
||||
'position': (position[0], position[1] + 2.5, position[2]),
|
||||
'model': ba.getmodel('tnt'),
|
||||
'light_model': ba.getmodel('tnt'),
|
||||
'body': 'crate',
|
||||
'body_scale': 3.3,
|
||||
'model_scale': 3.35,
|
||||
'shadow_size': 0.3,
|
||||
'color_texture': ba.gettexture('tickets'),
|
||||
'is_area_of_interest': True,
|
||||
'reflection': 'soft',
|
||||
'reflection_scale': [0.23],
|
||||
'materials': [self.box_material, shared.footing_material]
|
||||
})
|
||||
elif modeltype == 2:
|
||||
self.node = ba.newnode(
|
||||
'prop',
|
||||
delegate=self,
|
||||
attrs={
|
||||
'position': (position[0], position[1] + 1.5, position[2]),
|
||||
'model': ba.getmodel('tnt'),
|
||||
'light_model': ba.getmodel('tnt'),
|
||||
'body': 'crate',
|
||||
'body_scale': 1,
|
||||
'model_scale': 1,
|
||||
'shadow_size': 0.3,
|
||||
'color_texture': ba.gettexture('tnt'),
|
||||
'is_area_of_interest': True,
|
||||
'reflection': 'soft',
|
||||
'reflection_scale': [0.23],
|
||||
'materials': [self.box_material, shared.footing_material]
|
||||
})
|
||||
elif modeltype == 3:
|
||||
self.node = ba.newnode(
|
||||
'prop',
|
||||
delegate=self,
|
||||
attrs={
|
||||
'position': (position[0], position[1] + 1.5, position[2]),
|
||||
'model': ba.getmodel('puck'),
|
||||
'body': 'puck',
|
||||
'body_scale': 1,
|
||||
'model_scale': 1,
|
||||
'shadow_size': 1.0,
|
||||
'color_texture': ba.gettexture('puckColor'),
|
||||
'is_area_of_interest': True,
|
||||
'reflection': 'soft',
|
||||
'reflection_scale': [0.23],
|
||||
'materials': [self.box_material, shared.footing_material]
|
||||
})
|
||||
elif modeltype == 4:
|
||||
self.node = ba.newnode(
|
||||
'prop',
|
||||
delegate=self,
|
||||
attrs={
|
||||
'position': (position[0], position[1] + 1.5, position[2]),
|
||||
'model': ba.getmodel('frostyPelvis'),
|
||||
'body': 'sphere',
|
||||
'body_scale': 2.5,
|
||||
'model_scale': 2.5,
|
||||
'shadow_size': 0.3,
|
||||
'color_texture': ba.gettexture('frostyColor'),
|
||||
'is_area_of_interest': True,
|
||||
'reflection': 'soft',
|
||||
'reflection_scale': [1.0],
|
||||
'materials': [self.box_material, shared.footing_material]
|
||||
})
|
||||
|
||||
ba.animate(self.node, 'model_scale', {
|
||||
0: 0,
|
||||
0.2: self.node.model_scale * 1.1,
|
||||
0.26: self.node.model_scale})
|
||||
|
||||
light = ba.newnode(
|
||||
'light',
|
||||
owner=self.node,
|
||||
attrs={
|
||||
'radius': 0.28,
|
||||
'color': self.teamcolor
|
||||
})
|
||||
self.node.connectattr('position', light, 'position')
|
||||
|
||||
self._scoreboard()
|
||||
self._update()
|
||||
|
||||
def animate_model(self) -> None:
|
||||
if not self.node:
|
||||
return None
|
||||
ba.animate(self.node, 'model_scale', {
|
||||
0: self.node.model_scale,
|
||||
0.08: self.node.model_scale * 0.9,
|
||||
0.15: self.node.model_scale})
|
||||
if self.modeltype in [1,2]:
|
||||
ba.emitfx(position=self.node.position,
|
||||
velocity=self.node.velocity,
|
||||
count=int(6 + random.random() * 10),
|
||||
scale=0.5,
|
||||
spread=0.4,
|
||||
chunk_type='splinter')
|
||||
elif self.modeltype == 3:
|
||||
ba.emitfx(position=self.node.position,
|
||||
velocity=self.node.velocity,
|
||||
count=int(4 + random.random() * 4),
|
||||
scale=0.5,
|
||||
spread=0.3,
|
||||
chunk_type='metal')
|
||||
else:
|
||||
ba.emitfx(position=self.node.position,
|
||||
velocity=self.node.velocity,
|
||||
count=int(4 + random.random() * 4),
|
||||
scale=0.5,
|
||||
spread=0.3,
|
||||
chunk_type='ice')
|
||||
|
||||
def do_damage(self, msg: Any) -> None:
|
||||
if not self.node:
|
||||
return None
|
||||
damage = msg.magnitude
|
||||
self.hitpoints -= int(damage)
|
||||
if self.hitpoints <= 0:
|
||||
self.hitpoints = 0
|
||||
Blast(
|
||||
position=self.node.position,
|
||||
blast_radius=20.0,
|
||||
color=self.teamcolor).autoretain()
|
||||
self.node.delete()
|
||||
|
||||
def _update(self) -> None:
|
||||
self._score_text.node.text = str(self.hitpoints)
|
||||
self._bar_width = self.hitpoints * self._width_max / self.hitpoints_max
|
||||
cur_width = self._bar_scale.input0
|
||||
ba.animate(self._bar_scale, 'input0', {
|
||||
0.0: cur_width,
|
||||
0.1: self._bar_width
|
||||
})
|
||||
cur_x = self._bar_position.input0
|
||||
if self.team_str == 'team 1':
|
||||
ba.animate(self._bar_position, 'input0', {
|
||||
0.0: cur_x,
|
||||
0.1: self.bar_posx*0.265 - self._bar_width / 2
|
||||
})
|
||||
else:
|
||||
ba.animate(self._bar_position, 'input0', {
|
||||
0.0: cur_x,
|
||||
0.1: self.bar_posx + self._bar_width / 2
|
||||
})
|
||||
|
||||
def show_damage_msg(self, msg: Any) -> None:
|
||||
if not self.node:
|
||||
return None
|
||||
damage = msg.magnitude
|
||||
self.show_damage_count('-' + str(int(damage)),
|
||||
self.node.position,
|
||||
(msg.force_direction[0]*0.2,
|
||||
msg.force_direction[1]*0.2,
|
||||
msg.force_direction[2]*0.2,))
|
||||
|
||||
def show_damage_count(self, damage: str, position: Sequence[float],
|
||||
direction: Sequence[float]) -> None:
|
||||
"""Pop up a damage count at a position in space.
|
||||
|
||||
Category: Gameplay Functions
|
||||
"""
|
||||
lifespan = 1.0
|
||||
app = ba.app
|
||||
|
||||
# FIXME: Should never vary game elements based on local config.
|
||||
# (connected clients may have differing configs so they won't
|
||||
# get the intended results).
|
||||
do_big = app.ui.uiscale is ba.UIScale.SMALL or app.vr_mode
|
||||
txtnode = ba.newnode('text',
|
||||
attrs={
|
||||
'text': damage,
|
||||
'in_world': True,
|
||||
'h_align': 'center',
|
||||
'flatness': 1.0,
|
||||
'shadow': 1.0 if do_big else 0.7,
|
||||
'color': (1, 0.25, 0.25, 1),
|
||||
'scale': 0.035 if do_big else 0.03
|
||||
})
|
||||
# Translate upward.
|
||||
tcombine = ba.newnode('combine', owner=txtnode, attrs={'size': 3})
|
||||
tcombine.connectattr('output', txtnode, 'position')
|
||||
v_vals = []
|
||||
pval = 0.0
|
||||
vval = 0.07
|
||||
count = 6
|
||||
for i in range(count):
|
||||
v_vals.append((float(i) / count, pval))
|
||||
pval += vval
|
||||
vval *= 0.5
|
||||
p_start = position[0]
|
||||
p_dir = direction[0]
|
||||
ba.animate(tcombine, 'input0',
|
||||
{i[0] * lifespan: p_start + p_dir * i[1]
|
||||
for i in v_vals})
|
||||
p_start = position[1]
|
||||
p_dir = direction[1]
|
||||
ba.animate(tcombine, 'input1',
|
||||
{i[0] * lifespan: p_start + p_dir * i[1]
|
||||
for i in v_vals})
|
||||
p_start = position[2]
|
||||
p_dir = direction[2]
|
||||
ba.animate(tcombine, 'input2',
|
||||
{i[0] * lifespan: p_start + p_dir * i[1]
|
||||
for i in v_vals})
|
||||
ba.animate(txtnode, 'opacity', {0.7 * lifespan: 1.0, lifespan: 0.0})
|
||||
ba.timer(lifespan, txtnode.delete)
|
||||
|
||||
def _scoreboard(self) -> None:
|
||||
self._backing = ba.NodeActor(
|
||||
ba.newnode('image',
|
||||
attrs={
|
||||
'position': (self.bar_posx + self._width / 2, -35),
|
||||
'scale': (self._width, self._height),
|
||||
'opacity': 0.7,
|
||||
'color': (self.teamcolor[0] * 0.2,
|
||||
self.teamcolor[1] * 0.2,
|
||||
self.teamcolor[2] * 0.2),
|
||||
'vr_depth': -3,
|
||||
'attach': 'topCenter',
|
||||
'texture': self._backing_tex
|
||||
}))
|
||||
self._bar = ba.NodeActor(
|
||||
ba.newnode('image',
|
||||
attrs={
|
||||
'opacity': 1.0,
|
||||
'color': self.teamcolor,
|
||||
'attach': 'topCenter',
|
||||
'texture': self._bar_tex
|
||||
}))
|
||||
self._bar_scale = ba.newnode('combine',
|
||||
owner=self._bar.node,
|
||||
attrs={
|
||||
'size': 2,
|
||||
'input0': self._bar_width,
|
||||
'input1': self._bar_height
|
||||
})
|
||||
self._bar_scale.connectattr('output', self._bar.node, 'scale')
|
||||
self._bar_position = ba.newnode(
|
||||
'combine',
|
||||
owner=self._bar.node,
|
||||
attrs={
|
||||
'size': 2,
|
||||
'input0': self.bar_posx + self._bar_width / 2,
|
||||
'input1': -35
|
||||
})
|
||||
self._bar_position.connectattr('output', self._bar.node, 'position')
|
||||
self._cover = ba.NodeActor(
|
||||
ba.newnode('image',
|
||||
attrs={
|
||||
'position': (self.bar_posx + 120, -35),
|
||||
'scale':
|
||||
(self._width * 1.15, self._height * 1.6),
|
||||
'opacity': 1.0,
|
||||
'color': (self.teamcolor[0] * 1.1,
|
||||
self.teamcolor[1] * 1.1,
|
||||
self.teamcolor[2] * 1.1),
|
||||
'vr_depth': 2,
|
||||
'attach': 'topCenter',
|
||||
'texture': self._cover_tex,
|
||||
'model_transparent': self._model
|
||||
}))
|
||||
self._score_text = ba.NodeActor(
|
||||
ba.newnode('text',
|
||||
attrs={
|
||||
'position': (self.bar_posx + 120, -35),
|
||||
'h_attach': 'center',
|
||||
'v_attach': 'top',
|
||||
'h_align': 'center',
|
||||
'v_align': 'center',
|
||||
'maxwidth': 130,
|
||||
'scale': 0.9,
|
||||
'text': '',
|
||||
'shadow': 0.5,
|
||||
'flatness': 1.0,
|
||||
'color': (1,1,1,0.8)
|
||||
}))
|
||||
|
||||
def handlemessage(self, msg: Any) -> Any:
|
||||
if isinstance(msg, ba.HitMessage):
|
||||
self.animate_model()
|
||||
self.do_damage(msg)
|
||||
# self.show_damage_msg(msg)
|
||||
self._update()
|
||||
elif isinstance(msg, ba.DieMessage):
|
||||
if self.node:
|
||||
self.node.delete()
|
||||
elif isinstance(msg, ba.OutOfBoundsMessage):
|
||||
if self.node:
|
||||
self.node.position = self.position
|
||||
self.node.velocity = (0,0,0)
|
||||
else:
|
||||
super().handlemessage(msg)
|
||||
|
||||
class Player(ba.Player['Team']):
|
||||
"""Our player type for this game."""
|
||||
|
||||
|
||||
class Team(ba.Team[Player]):
|
||||
"""Our team type for this game."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.score = 0
|
||||
self.can_attack: bool = False
|
||||
self.tnt: Optional[TNTBox] = None
|
||||
|
||||
|
||||
# ba_meta export game
|
||||
class TNTTeamGame(ba.TeamGameActivity[Player, Team]):
|
||||
"""Football game for teams mode."""
|
||||
|
||||
name = 'Heist'
|
||||
description = 'Get the enemies Ticket Vault!'
|
||||
announce_player_deaths = True
|
||||
|
||||
@classmethod
|
||||
def get_available_settings(
|
||||
cls, sessiontype: type[ba.Session]) -> list[ba.Setting]:
|
||||
settings = [
|
||||
ba.IntSetting(
|
||||
'TNT Hitpoints',
|
||||
min_value=1000,
|
||||
default=25000,
|
||||
increment=1000,
|
||||
),
|
||||
ba.FloatChoiceSetting(
|
||||
'Model Type',
|
||||
choices=[
|
||||
('TNT Big', 1),
|
||||
('TNT', 2),
|
||||
('Puck', 3),
|
||||
('Snowball', 4),
|
||||
],
|
||||
default=1,
|
||||
),
|
||||
ba.IntChoiceSetting(
|
||||
'Time Limit',
|
||||
choices=[
|
||||
('None', 0),
|
||||
('1 Minute', 60),
|
||||
('2 Minutes', 120),
|
||||
('5 Minutes', 300),
|
||||
('10 Minutes', 600),
|
||||
('20 Minutes', 1200),
|
||||
],
|
||||
default=0,
|
||||
),
|
||||
ba.FloatChoiceSetting(
|
||||
'Respawn Times',
|
||||
choices=[
|
||||
('Shorter', 0.25),
|
||||
('Short', 0.5),
|
||||
('Normal', 1.0),
|
||||
('Long', 2.0),
|
||||
('Longer', 4.0),
|
||||
],
|
||||
default=1.0,
|
||||
),
|
||||
ba.BoolSetting('Epic Mode', default=False),
|
||||
]
|
||||
return settings
|
||||
|
||||
@classmethod
|
||||
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
|
||||
# We only support two-team play.
|
||||
return issubclass(sessiontype, ba.DualTeamSession)
|
||||
|
||||
@classmethod
|
||||
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
|
||||
return ba.getmaps('team_flag')
|
||||
|
||||
def __init__(self, settings: dict):
|
||||
super().__init__(settings)
|
||||
self._time_limit = float(settings['Time Limit'])
|
||||
self._tnt_hitpoints = int(settings['TNT Hitpoints'])
|
||||
self._model_type = float(settings['Model Type'])
|
||||
self._tntbox_pos = [(-11, 2.5, 0.0), (11.0, 2.5, 0.0)]
|
||||
self.team_index = 1
|
||||
self.create_team_index = 1
|
||||
self._bots = SpazBotSet()
|
||||
|
||||
def get_instance_description(self) -> Union[str, Sequence]:
|
||||
return 'Get the enemies Ticket Vault!'
|
||||
|
||||
def get_instance_description_short(self) -> Union[str, Sequence]:
|
||||
return 'Get the enemies Ticket Vault!'
|
||||
|
||||
def on_team_join(self, team: Team) -> None:
|
||||
# Can't do this in create_team because the team's color/etc. have
|
||||
# not been wired up yet at that point.
|
||||
self._spawn_tnt_for_team(team)
|
||||
|
||||
def _spawn_tnt_for_team(self, team: Team) -> None:
|
||||
team.tnt = TNTBox(team_id=team,
|
||||
modeltype=self._model_type,
|
||||
position=self.map.get_flag_position(team.id),
|
||||
hitpoints=self._tnt_hitpoints,
|
||||
team='team ' + str(self.team_index)).autoretain()
|
||||
self.team_index += 1
|
||||
|
||||
def on_begin(self) -> None:
|
||||
super().on_begin()
|
||||
self.setup_standard_time_limit(self._time_limit)
|
||||
ba.timer(0.05, self._update, repeat=True)
|
||||
ba.timer(10.0, self.custom_drop, repeat=True)
|
||||
# self.setup_standard_powerup_drops()
|
||||
|
||||
def custom_drop(self):
|
||||
pos = self.map.get_flag_position(None)
|
||||
def spawn_punch():
|
||||
PowerupBox(
|
||||
position=(pos[0], pos[1] + 2.0, pos[2]),
|
||||
poweruptype='punch',
|
||||
expire=False).autoretain()
|
||||
def spawn_shield():
|
||||
PowerupBox(
|
||||
position=(pos[0], pos[1] + 2.0, pos[2]),
|
||||
poweruptype='shield',
|
||||
expire=False).autoretain()
|
||||
def spawn_explodeybot():
|
||||
self._bots._spawn_bot(
|
||||
ExplodeyBotNoTimeLimit,
|
||||
pos=(pos[0], pos[1] + 1.0, pos[2]),
|
||||
on_spawn_call=None)
|
||||
custom = random.choice([spawn_punch, spawn_shield, spawn_explodeybot])
|
||||
spawner.Spawner(
|
||||
pt=pos,
|
||||
spawn_time=3.0,
|
||||
send_spawn_message=False,
|
||||
spawn_callback=custom)
|
||||
|
||||
def _update(self) -> None:
|
||||
if not self.teams[0].tnt.node:
|
||||
self.teams[1].score = 1
|
||||
if not self.teams[1].tnt.node:
|
||||
self.teams[0].score = 1
|
||||
if self.teams[0].score > 0 or self.teams[1].score > 0:
|
||||
ba.timer(1.0, self.end_game)
|
||||
|
||||
def spawn_player(self, player: Player) -> ba.Actor:
|
||||
team: Team = player.team
|
||||
spaz = self.spawn_player_spaz(player)
|
||||
spaz.connect_controls_to_player(enable_bomb=False)
|
||||
return spaz
|
||||
|
||||
|
||||
def handlemessage(self, msg: Any) -> Any:
|
||||
if isinstance(msg, ba.PlayerDiedMessage):
|
||||
# Augment standard behavior.
|
||||
super().handlemessage(msg)
|
||||
player = msg.getplayer(Player)
|
||||
self.respawn_player(player)
|
||||
else:
|
||||
return super().handlemessage(msg)
|
||||
return None
|
||||
|
||||
def end_game(self) -> None:
|
||||
results = ba.GameResults()
|
||||
for team in self.teams:
|
||||
results.set_team_score(team, team.score)
|
||||
self.end(results=results, announce_delay=0.8)
|
||||
1551
dist/ba_root/mods/games/Hot-Bomb.py
vendored
Normal file
1551
dist/ba_root/mods/games/Hot-Bomb.py
vendored
Normal file
File diff suppressed because it is too large
Load diff
BIN
dist/ba_root/mods/games/LaserTracer.so
vendored
Normal file
BIN
dist/ba_root/mods/games/LaserTracer.so
vendored
Normal file
Binary file not shown.
62
dist/ba_root/mods/games/MemoryGame.py
vendored
62
dist/ba_root/mods/games/MemoryGame.py
vendored
|
|
@ -936,65 +936,3 @@ class MGgame(ba.TeamGameActivity[Player, Team]):
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class MGdefs():
|
||||
points = {}
|
||||
boxes = {}
|
||||
points['flag_default'] = (0.17358, 3.75764, 1.99124)
|
||||
boxes['area_of_interest_bounds'] = (0.3544110667, 4.493562578, -2.518391331) + (0.0, 0.0, 0.0) + (16.64754831, 8.06138989, 18.5029888)
|
||||
boxes['map_bounds'] = (0.2608783669, 4.899663734, -3.543675157) + (0.0, 0.0, 0.0) + (29.23565494, 14.19991443, 29.92689344)
|
||||
|
||||
class MGmap(ba.Map):
|
||||
defs = MGdefs()
|
||||
name = 'Sky Tiles'
|
||||
|
||||
@classmethod
|
||||
def get_play_types(cls) -> List[str]:
|
||||
"""Return valid play types for this map."""
|
||||
return []
|
||||
|
||||
@classmethod
|
||||
def get_preview_texture_name(cls) -> str:
|
||||
return 'achievementOffYouGo'
|
||||
|
||||
@classmethod
|
||||
def on_preload(cls) -> Any:
|
||||
data: Dict[str, Any] = {
|
||||
'bgtex': ba.gettexture('menuBG'),
|
||||
'bgmodel': ba.getmodel('thePadBG')
|
||||
}
|
||||
return data
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
shared = SharedObjects.get()
|
||||
self.node = ba.newnode(
|
||||
'terrain',
|
||||
attrs={
|
||||
'model': self.preloaddata['bgmodel'],
|
||||
'lighting': False,
|
||||
'background': True,
|
||||
'color_texture': self.preloaddata['bgtex']
|
||||
})
|
||||
gnode = ba.getactivity().globalsnode
|
||||
gnode.tint = (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_inner = (0.9, 0.9, 0.9)
|
||||
gnode.vr_camera_offset = (0, -0.8, -1.1)
|
||||
gnode.vr_near_clip = 0.5
|
||||
|
||||
|
||||
|
||||
|
||||
# Plugin only for our map UwU
|
||||
|
||||
# ba_meta export plugin
|
||||
class byFreaku(ba.Plugin):
|
||||
def on_app_launch(self):
|
||||
ba._map.register_map(MGmap)
|
||||
233
dist/ba_root/mods/games/MusicalFlags.py
vendored
Normal file
233
dist/ba_root/mods/games/MusicalFlags.py
vendored
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
## Made by MattZ45986 on GitHub
|
||||
## Ported by: Freaku / @[Just] Freak#4999
|
||||
|
||||
|
||||
#Bug Fixes & Improvements as well...
|
||||
|
||||
#Join BCS:
|
||||
# https://discord.gg/ucyaesh
|
||||
|
||||
|
||||
|
||||
|
||||
from __future__ import annotations
|
||||
from typing import TYPE_CHECKING
|
||||
import _ba,ba,random,math
|
||||
from bastd.actor.flag import Flag,FlagPickedUpMessage
|
||||
from bastd.actor.playerspaz import PlayerSpaz
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Type, List, Dict, Tuple, Union, Sequence, Optional
|
||||
|
||||
|
||||
|
||||
class Player(ba.Player['Team']):
|
||||
def __init__(self) -> None:
|
||||
self.done: bool = False
|
||||
self.survived: bool = True
|
||||
|
||||
class Team(ba.Team[Player]):
|
||||
def __init__(self) -> None:
|
||||
self.score = 0
|
||||
|
||||
|
||||
# ba_meta require api 6
|
||||
# ba_meta export game
|
||||
class MFGame(ba.TeamGameActivity[Player, Team]):
|
||||
name = 'Musical Flags'
|
||||
description = "Don't be the one stuck without a flag!"
|
||||
|
||||
@classmethod
|
||||
def get_available_settings(
|
||||
cls, sessiontype: Type[ba.Session]) -> List[ba.Setting]:
|
||||
settings = [
|
||||
ba.IntChoiceSetting(
|
||||
'Time Limit',
|
||||
choices=[
|
||||
('None', 0),
|
||||
('1 Minute', 60),
|
||||
('2 Minutes', 120),
|
||||
('5 Minutes', 300),
|
||||
('10 Minutes', 600),
|
||||
('20 Minutes', 1200),
|
||||
],
|
||||
default=0,
|
||||
),
|
||||
ba.BoolSetting('Epic Mode', default=False),
|
||||
ba.BoolSetting('Enable Running', default=True),
|
||||
ba.BoolSetting('Enable Punching', default=False),
|
||||
ba.BoolSetting('Enable Bottom Credit', True)
|
||||
]
|
||||
return settings
|
||||
|
||||
@classmethod
|
||||
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
|
||||
return (issubclass(sessiontype, ba.DualTeamSession)
|
||||
or issubclass(sessiontype, ba.FreeForAllSession))
|
||||
|
||||
@classmethod
|
||||
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
|
||||
return ['Doom Shroom']
|
||||
|
||||
def __init__(self, settings: dict):
|
||||
super().__init__(settings)
|
||||
self.nodes = []
|
||||
self._dingsound = ba.getsound('dingSmall')
|
||||
self._epic_mode = bool(settings['Epic Mode'])
|
||||
self.credit_text = bool(settings['Enable Bottom Credit'])
|
||||
self._time_limit = float(settings['Time Limit'])
|
||||
self.is_punch = bool(settings['Enable Punching'])
|
||||
self.is_run = bool(settings['Enable Running'])
|
||||
|
||||
self._textRound = ba.newnode('text',
|
||||
attrs={'text': '',
|
||||
'position': (0, -38),
|
||||
'scale': 1,
|
||||
'shadow': 1.0,
|
||||
'flatness': 1.0,
|
||||
'color': (1.0, 0.0, 1.0),
|
||||
'opacity': 1,
|
||||
'v_attach': 'top',
|
||||
'h_attach': 'center',
|
||||
'h_align': 'center',
|
||||
'v_align': 'center'})
|
||||
|
||||
self.slow_motion = self._epic_mode
|
||||
# A cool music, matching our gamemode theme
|
||||
self.default_music = ba.MusicType.FLAG_CATCHER
|
||||
|
||||
def get_instance_description(self) -> Union[str, Sequence]:
|
||||
return 'Catch Flag for yourself'
|
||||
|
||||
def get_instance_description_short(self) -> Union[str, Sequence]:
|
||||
return 'Catch Flag for yourself'
|
||||
|
||||
def on_player_join(self, player: Player) -> None:
|
||||
if self.has_begun():
|
||||
ba.screenmessage(
|
||||
ba.Lstr(resource='playerDelayedJoinText',
|
||||
subs=[('${PLAYER}', player.getname(full=True))]),
|
||||
color=(0, 1, 0),transient=True)
|
||||
player.survived = False
|
||||
return
|
||||
self.spawn_player(player)
|
||||
|
||||
def on_player_leave(self, player: Player) -> None:
|
||||
super().on_player_leave(player)
|
||||
# A departing player may trigger game-over.
|
||||
self.checkEnd()
|
||||
|
||||
def on_begin(self) -> None:
|
||||
super().on_begin()
|
||||
self.roundNum = 0
|
||||
self.numPickedUp = 0
|
||||
self.nodes = []
|
||||
self.flags = []
|
||||
self.spawned = []
|
||||
self.setup_standard_time_limit(self._time_limit)
|
||||
import base64
|
||||
exec(base64.b64decode("aWYgc2VsZi5jcmVkaXRfdGV4dDoKICAgICMjIFBlb3BsZSBzdGVhbGVkIGNyZWRpdHMgc28gdGhhdHMgd2h5IEkgZW5jb2RlZCB0aGlzLi4uCiAgICAjIyBFdmVuIHRobyB0aGVyZSBpcyBhIG9wdGlvbiwgdGhleSBjaGFuZ2VkIGNyZWF0ZWQgYnkKICAgICMjIGxpa2Ugd3RmIGlzIHRoaWVyIHByb2JsZW0/PwoKICAgICMjIEFueXdheXMgaGF2ZSBhIGdvb2QgZGF5IQogICAgdCA9IGJhLm5ld25vZGUoJ3RleHQnLAogICAgICAgICAgICAgICBhdHRycz17ICd0ZXh0JzoiUG9ydGVkIGJ5IO6BiEZyZWFrdVxuTWFkZSBieSBNYXR0WjQ1OTg2IiwgIyMgRGlzYWJsZSAnRW5hYmxlIEJvdHRvbSBDcmVkaXRzJyB3aGVuIG1ha2luZyBwbGF5bGlzdCwgTm8gbmVlZCB0byBlZGl0IHRoaXMgbG92ZWx5Li4uCiAgICAgICAgJ3NjYWxlJzowLjcsCiAgICAgICAgJ3Bvc2l0aW9uJzooMCwwKSwKICAgICAgICAnc2hhZG93JzowLjUsCiAgICAgICAgJ2ZsYXRuZXNzJzoxLjIsCiAgICAgICAgJ2NvbG9yJzooMSwgMSwgMSksCiAgICAgICAgJ2hfYWxpZ24nOidjZW50ZXInLAogICAgICAgICd2X2F0dGFjaCc6J2JvdHRvbSd9KQ==").decode('UTF-8'))
|
||||
self.makeRound()
|
||||
self._textRound.text = 'Round ' + str(self.roundNum)
|
||||
ba.timer(5, self.checkEnd)
|
||||
|
||||
def makeRound(self):
|
||||
for player in self.players:
|
||||
if player.survived: player.team.score += 1
|
||||
self.roundNum += 1
|
||||
self._textRound.text = 'Round ' + str(self.roundNum)
|
||||
self.flags = []
|
||||
self.spawned = []
|
||||
angle = random.randint(0,359)
|
||||
c=0
|
||||
for player in self.players:
|
||||
if player.survived: c+=1
|
||||
spacing = 10
|
||||
for player in self.players:
|
||||
player.done = False
|
||||
if player.survived:
|
||||
if not player.is_alive():
|
||||
self.spawn_player(player,(.5,5,-4))
|
||||
self.spawned.append(player)
|
||||
try: spacing = 360 // (c)
|
||||
except: self.checkEnd()
|
||||
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)]
|
||||
# Smart Mathematics:
|
||||
# All Flags spawn same distance from the players
|
||||
for i in range(c-1):
|
||||
angle += spacing
|
||||
angle %= 360
|
||||
x=6 * math.sin(math.degrees(angle))
|
||||
z=6 * math.cos(math.degrees(angle))
|
||||
flag = Flag(position=(x+.5,5,z-4), color=colors[i]).autoretain()
|
||||
self.flags.append(flag)
|
||||
|
||||
def killRound(self):
|
||||
self.numPickedUp = 0
|
||||
for player in self.players:
|
||||
if player.is_alive(): player.actor.handlemessage(ba.DieMessage())
|
||||
for flag in self.flags: flag.node.delete()
|
||||
for light in self.nodes: light.delete()
|
||||
|
||||
def spawn_player(self, player: Player, pos: tuple = (0,0,0)) -> ba.Actor:
|
||||
spaz = self.spawn_player_spaz(player)
|
||||
if pos == (0,0,0):
|
||||
pos = (-.5+random.random()*2,3+random.random()*2,-5+random.random()*2)
|
||||
spaz.connect_controls_to_player(enable_punch=self.is_punch, enable_bomb=False, enable_run=self.is_run)
|
||||
spaz.handlemessage(ba.StandMessage(pos))
|
||||
return spaz
|
||||
|
||||
def check_respawn(self, player):
|
||||
if not player.done and player.survived:
|
||||
self.respawn_player(player, 2.5)
|
||||
|
||||
def handlemessage(self, msg: Any) -> Any:
|
||||
|
||||
if isinstance(msg, ba.PlayerDiedMessage):
|
||||
super().handlemessage(msg)
|
||||
player = msg.getplayer(Player)
|
||||
ba.timer(0.1, ba.Call(self.check_respawn, player))
|
||||
ba.timer(0.5, self.checkEnd)
|
||||
elif isinstance(msg, FlagPickedUpMessage):
|
||||
self.numPickedUp += 1
|
||||
msg.node.getdelegate(PlayerSpaz, True).getplayer(Player, True).done = True
|
||||
l = ba.newnode('light',
|
||||
owner=None,
|
||||
attrs={'color':msg.node.color,
|
||||
'position':(msg.node.position_center),
|
||||
'intensity':1})
|
||||
self.nodes.append(l)
|
||||
msg.flag.handlemessage(ba.DieMessage())
|
||||
msg.node.handlemessage(ba.DieMessage())
|
||||
msg.node.delete()
|
||||
if self.numPickedUp == len(self.flags):
|
||||
for player in self.spawned:
|
||||
if not player.done:
|
||||
try:
|
||||
player.survived = False
|
||||
ba.screenmessage("No Flag? "+player.getname())
|
||||
player.actor.handlemessage(ba.StandMessage((0,3,-2)))
|
||||
ba.timer(0.5,ba.Call(player.actor.handlemessage, ba.FreezeMessage()))
|
||||
ba.timer(3,ba.Call(player.actor.handlemessage, ba.ShouldShatterMessage()))
|
||||
except: pass
|
||||
ba.timer(3.5,self.killRound)
|
||||
ba.timer(3.55,self.makeRound)
|
||||
else:
|
||||
return super().handlemessage(msg)
|
||||
return None
|
||||
|
||||
def checkEnd(self):
|
||||
i = 0
|
||||
for player in self.players:
|
||||
if player.survived:
|
||||
i+=1
|
||||
if i <= 1:
|
||||
for player in self.players:
|
||||
if player.survived:
|
||||
player.team.score += 10
|
||||
ba.timer(2.5, self.end_game)
|
||||
|
||||
def end_game(self) -> None:
|
||||
results = ba.GameResults()
|
||||
for team in self.teams:
|
||||
results.set_team_score(team, team.score)
|
||||
self.end(results=results)
|
||||
722
dist/ba_root/mods/games/Reverserace.py
vendored
Normal file
722
dist/ba_root/mods/games/Reverserace.py
vendored
Normal file
|
|
@ -0,0 +1,722 @@
|
|||
|
||||
# Released under the MIT License. See LICENSE for details.
|
||||
#
|
||||
"""Defines Race mini-game."""
|
||||
# Created inside BCS (Bombsquad consultancy services)
|
||||
# discord.gg/ucyaesh
|
||||
# https://bombsquad.ga
|
||||
# - Reverse Race by Mr.Smoothy
|
||||
# ba_meta require api 6
|
||||
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import random
|
||||
from typing import TYPE_CHECKING
|
||||
from dataclasses import dataclass
|
||||
|
||||
import ba
|
||||
from bastd.actor.bomb import Bomb
|
||||
from bastd.actor.playerspaz import PlayerSpaz
|
||||
from bastd.actor.scoreboard import Scoreboard
|
||||
from bastd.gameutils import SharedObjects
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import (Any, Type, Tuple, List, Sequence, Optional, Dict,
|
||||
Union)
|
||||
from bastd.actor.onscreentimer import OnScreenTimer
|
||||
|
||||
|
||||
@dataclass
|
||||
class RaceMine:
|
||||
"""Holds info about a mine on the track."""
|
||||
point: Sequence[float]
|
||||
mine: Optional[Bomb]
|
||||
|
||||
|
||||
class RaceRegion(ba.Actor):
|
||||
"""Region used to track progress during a race."""
|
||||
|
||||
def __init__(self, pt: Sequence[float], index: int):
|
||||
super().__init__()
|
||||
activity = self.activity
|
||||
assert isinstance(activity, ReverseRaceGame)
|
||||
self.pos = pt
|
||||
self.index = index
|
||||
self.node = ba.newnode(
|
||||
'region',
|
||||
delegate=self,
|
||||
attrs={
|
||||
'position': pt[:3],
|
||||
'scale': (pt[3] * 2.0, pt[4] * 2.0, pt[5] * 2.0),
|
||||
'type': 'box',
|
||||
'materials': [activity.race_region_material]
|
||||
})
|
||||
|
||||
|
||||
class Player(ba.Player['Team']):
|
||||
"""Our player type for this game."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.distance_txt: Optional[ba.Node] = None
|
||||
self.last_region = 0
|
||||
self.lap = 0
|
||||
self.distance = 0.0
|
||||
self.finished = False
|
||||
self.rank: Optional[int] = None
|
||||
|
||||
|
||||
class Team(ba.Team[Player]):
|
||||
"""Our team type for this game."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.time: Optional[float] = None
|
||||
self.lap = 0
|
||||
self.finished = False
|
||||
|
||||
|
||||
# ba_meta export game
|
||||
class ReverseRaceGame(ba.TeamGameActivity[Player, Team]):
|
||||
"""Game of racing around a track."""
|
||||
|
||||
name = 'Reverse Race'
|
||||
description = 'Run real fast! \n but in reverse direction'
|
||||
scoreconfig = ba.ScoreConfig(label='Time',
|
||||
lower_is_better=True,
|
||||
scoretype=ba.ScoreType.MILLISECONDS)
|
||||
|
||||
@classmethod
|
||||
def get_available_settings(
|
||||
cls, sessiontype: Type[ba.Session]) -> List[ba.Setting]:
|
||||
settings = [
|
||||
ba.IntSetting('Laps', min_value=1, default=3, increment=1),
|
||||
ba.IntChoiceSetting(
|
||||
'Time Limit',
|
||||
default=0,
|
||||
choices=[
|
||||
('None', 0),
|
||||
('1 Minute', 60),
|
||||
('2 Minutes', 120),
|
||||
('5 Minutes', 300),
|
||||
('10 Minutes', 600),
|
||||
('20 Minutes', 1200),
|
||||
],
|
||||
),
|
||||
ba.IntChoiceSetting(
|
||||
'Mine Spawning',
|
||||
default=4000,
|
||||
choices=[
|
||||
('No Mines', 0),
|
||||
('8 Seconds', 8000),
|
||||
('4 Seconds', 4000),
|
||||
('2 Seconds', 2000),
|
||||
],
|
||||
),
|
||||
ba.IntChoiceSetting(
|
||||
'Bomb Spawning',
|
||||
choices=[
|
||||
('None', 0),
|
||||
('8 Seconds', 8000),
|
||||
('4 Seconds', 4000),
|
||||
('2 Seconds', 2000),
|
||||
('1 Second', 1000),
|
||||
],
|
||||
default=2000,
|
||||
),
|
||||
ba.BoolSetting('Epic Mode', default=False),
|
||||
]
|
||||
|
||||
# We have some specific settings in teams mode.
|
||||
if issubclass(sessiontype, ba.DualTeamSession):
|
||||
settings.append(
|
||||
ba.BoolSetting('Entire Team Must Finish', default=False))
|
||||
return settings
|
||||
|
||||
@classmethod
|
||||
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
|
||||
return issubclass(sessiontype, ba.MultiTeamSession)
|
||||
|
||||
@classmethod
|
||||
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
|
||||
return ba.getmaps('race')
|
||||
|
||||
def __init__(self, settings: dict):
|
||||
self._race_started = False
|
||||
super().__init__(settings)
|
||||
self._scoreboard = Scoreboard()
|
||||
self._score_sound = ba.getsound('score')
|
||||
self._swipsound = ba.getsound('swip')
|
||||
self._last_team_time: Optional[float] = None
|
||||
self._front_race_region: Optional[int] = None
|
||||
self._nub_tex = ba.gettexture('nub')
|
||||
self._beep_1_sound = ba.getsound('raceBeep1')
|
||||
self._beep_2_sound = ba.getsound('raceBeep2')
|
||||
self.race_region_material: Optional[ba.Material] = None
|
||||
self._regions: List[RaceRegion] = []
|
||||
self._team_finish_pts: Optional[int] = None
|
||||
self._time_text: Optional[ba.Actor] = None
|
||||
self._timer: Optional[OnScreenTimer] = None
|
||||
self._race_mines: Optional[List[RaceMine]] = None
|
||||
self._race_mine_timer: Optional[ba.Timer] = None
|
||||
self._scoreboard_timer: Optional[ba.Timer] = None
|
||||
self._player_order_update_timer: Optional[ba.Timer] = None
|
||||
self._start_lights: Optional[List[ba.Node]] = None
|
||||
self._bomb_spawn_timer: Optional[ba.Timer] = None
|
||||
self._laps = int(settings['Laps'])
|
||||
self._entire_team_must_finish = bool(
|
||||
settings.get('Entire Team Must Finish', False))
|
||||
self._time_limit = float(settings['Time Limit'])
|
||||
self._mine_spawning = int(settings['Mine Spawning'])
|
||||
self._bomb_spawning = int(settings['Bomb Spawning'])
|
||||
self._epic_mode = bool(settings['Epic Mode'])
|
||||
|
||||
# Base class overrides.
|
||||
self.slow_motion = self._epic_mode
|
||||
self.default_music = (ba.MusicType.EPIC_RACE
|
||||
if self._epic_mode else ba.MusicType.RACE)
|
||||
|
||||
def get_instance_description(self) -> Union[str, Sequence]:
|
||||
if (isinstance(self.session, ba.DualTeamSession)
|
||||
and self._entire_team_must_finish):
|
||||
t_str = ' Your entire team has to finish.'
|
||||
else:
|
||||
t_str = ''
|
||||
|
||||
if self._laps > 1:
|
||||
return 'Run ${ARG1} laps.' + t_str, self._laps
|
||||
return 'Run 1 lap.' + t_str
|
||||
|
||||
def get_instance_description_short(self) -> Union[str, Sequence]:
|
||||
if self._laps > 1:
|
||||
return 'run ${ARG1} laps in reverse direction', self._laps
|
||||
return 'run 1 lap'
|
||||
|
||||
def on_transition_in(self) -> None:
|
||||
super().on_transition_in()
|
||||
shared = SharedObjects.get()
|
||||
pts = self.map.get_def_points('race_point')
|
||||
mat = self.race_region_material = ba.Material()
|
||||
mat.add_actions(conditions=('they_have_material',
|
||||
shared.player_material),
|
||||
actions=(
|
||||
('modify_part_collision', 'collide', True),
|
||||
('modify_part_collision', 'physical', False),
|
||||
('call', 'at_connect',
|
||||
self._handle_race_point_collide),
|
||||
))
|
||||
self._regions.append(RaceRegion(pts[0], len(self._regions)))
|
||||
|
||||
pts.reverse()
|
||||
for rpt in pts[:-1]:
|
||||
self._regions.append(RaceRegion(rpt, len(self._regions)))
|
||||
|
||||
def _flash_player(self, player: Player, scale: float) -> None:
|
||||
assert isinstance(player.actor, PlayerSpaz)
|
||||
assert player.actor.node
|
||||
pos = player.actor.node.position
|
||||
light = ba.newnode('light',
|
||||
attrs={
|
||||
'position': pos,
|
||||
'color': (1, 1, 0),
|
||||
'height_attenuated': False,
|
||||
'radius': 0.4
|
||||
})
|
||||
ba.timer(0.5, light.delete)
|
||||
ba.animate(light, 'intensity', {0: 0, 0.1: 1.0 * scale, 0.5: 0})
|
||||
|
||||
def _handle_race_point_collide(self) -> None:
|
||||
# FIXME: Tidy this up.
|
||||
# pylint: disable=too-many-statements
|
||||
# pylint: disable=too-many-branches
|
||||
# pylint: disable=too-many-nested-blocks
|
||||
collision = ba.getcollision()
|
||||
try:
|
||||
region = collision.sourcenode.getdelegate(RaceRegion, True)
|
||||
player = collision.opposingnode.getdelegate(PlayerSpaz,
|
||||
True).getplayer(
|
||||
Player, True)
|
||||
except ba.NotFoundError:
|
||||
return
|
||||
|
||||
last_region = player.last_region
|
||||
this_region = region.index
|
||||
|
||||
if last_region != this_region:
|
||||
|
||||
# If a player tries to skip regions, smite them.
|
||||
# Allow a one region leeway though (its plausible players can get
|
||||
# blown over a region, etc).
|
||||
if this_region > last_region + 2:
|
||||
if player.is_alive():
|
||||
assert player.actor
|
||||
player.actor.handlemessage(ba.DieMessage())
|
||||
ba.screenmessage(ba.Lstr(
|
||||
translate=('statements', 'Killing ${NAME} for'
|
||||
' skipping part of the track!'),
|
||||
subs=[('${NAME}', player.getname(full=True))]),
|
||||
color=(1, 0, 0))
|
||||
else:
|
||||
# If this player is in first, note that this is the
|
||||
# front-most race-point.
|
||||
if player.rank == 0:
|
||||
self._front_race_region = this_region
|
||||
|
||||
player.last_region = this_region
|
||||
if last_region >= len(self._regions) - 2 and this_region == 0:
|
||||
team = player.team
|
||||
player.lap = min(self._laps, player.lap + 1)
|
||||
|
||||
# In teams mode with all-must-finish on, the team lap
|
||||
# value is the min of all team players.
|
||||
# Otherwise its the max.
|
||||
if isinstance(self.session, ba.DualTeamSession
|
||||
) and self._entire_team_must_finish:
|
||||
team.lap = min([p.lap for p in team.players])
|
||||
else:
|
||||
team.lap = max([p.lap for p in team.players])
|
||||
|
||||
# A player is finishing.
|
||||
if player.lap == self._laps:
|
||||
|
||||
# In teams mode, hand out points based on the order
|
||||
# players come in.
|
||||
if isinstance(self.session, ba.DualTeamSession):
|
||||
assert self._team_finish_pts is not None
|
||||
if self._team_finish_pts > 0:
|
||||
self.stats.player_scored(player,
|
||||
self._team_finish_pts,
|
||||
screenmessage=False)
|
||||
self._team_finish_pts -= 25
|
||||
|
||||
# Flash where the player is.
|
||||
self._flash_player(player, 1.0)
|
||||
player.finished = True
|
||||
assert player.actor
|
||||
player.actor.handlemessage(
|
||||
ba.DieMessage(immediate=True))
|
||||
|
||||
# Makes sure noone behind them passes them in rank
|
||||
# while finishing.
|
||||
player.distance = 9999.0
|
||||
|
||||
# If the whole team has finished the race.
|
||||
if team.lap == self._laps:
|
||||
ba.playsound(self._score_sound)
|
||||
player.team.finished = True
|
||||
assert self._timer is not None
|
||||
elapsed = ba.time() - self._timer.getstarttime()
|
||||
self._last_team_time = player.team.time = elapsed
|
||||
self._check_end_game()
|
||||
|
||||
# Team has yet to finish.
|
||||
else:
|
||||
ba.playsound(self._swipsound)
|
||||
|
||||
# They've just finished a lap but not the race.
|
||||
else:
|
||||
ba.playsound(self._swipsound)
|
||||
self._flash_player(player, 0.3)
|
||||
|
||||
# Print their lap number over their head.
|
||||
try:
|
||||
assert isinstance(player.actor, PlayerSpaz)
|
||||
mathnode = ba.newnode('math',
|
||||
owner=player.actor.node,
|
||||
attrs={
|
||||
'input1': (0, 1.9, 0),
|
||||
'operation': 'add'
|
||||
})
|
||||
player.actor.node.connectattr(
|
||||
'torso_position', mathnode, 'input2')
|
||||
tstr = ba.Lstr(resource='lapNumberText',
|
||||
subs=[('${CURRENT}',
|
||||
str(player.lap + 1)),
|
||||
('${TOTAL}', str(self._laps))
|
||||
])
|
||||
txtnode = ba.newnode('text',
|
||||
owner=mathnode,
|
||||
attrs={
|
||||
'text': tstr,
|
||||
'in_world': True,
|
||||
'color': (1, 1, 0, 1),
|
||||
'scale': 0.015,
|
||||
'h_align': 'center'
|
||||
})
|
||||
mathnode.connectattr('output', txtnode, 'position')
|
||||
ba.animate(txtnode, 'scale', {
|
||||
0.0: 0,
|
||||
0.2: 0.019,
|
||||
2.0: 0.019,
|
||||
2.2: 0
|
||||
})
|
||||
ba.timer(2.3, mathnode.delete)
|
||||
except Exception:
|
||||
ba.print_exception('Error printing lap.')
|
||||
|
||||
def on_team_join(self, team: Team) -> None:
|
||||
self._update_scoreboard()
|
||||
|
||||
def on_player_leave(self, player: Player) -> None:
|
||||
super().on_player_leave(player)
|
||||
|
||||
# A player leaving disqualifies the team if 'Entire Team Must Finish'
|
||||
# is on (otherwise in teams mode everyone could just leave except the
|
||||
# leading player to win).
|
||||
if (isinstance(self.session, ba.DualTeamSession)
|
||||
and self._entire_team_must_finish):
|
||||
ba.screenmessage(ba.Lstr(
|
||||
translate=('statements',
|
||||
'${TEAM} is disqualified because ${PLAYER} left'),
|
||||
subs=[('${TEAM}', player.team.name),
|
||||
('${PLAYER}', player.getname(full=True))]),
|
||||
color=(1, 1, 0))
|
||||
player.team.finished = True
|
||||
player.team.time = None
|
||||
player.team.lap = 0
|
||||
ba.playsound(ba.getsound('boo'))
|
||||
for otherplayer in player.team.players:
|
||||
otherplayer.lap = 0
|
||||
otherplayer.finished = True
|
||||
try:
|
||||
if otherplayer.actor is not None:
|
||||
otherplayer.actor.handlemessage(ba.DieMessage())
|
||||
except Exception:
|
||||
ba.print_exception('Error sending DieMessage.')
|
||||
|
||||
# Defer so team/player lists will be updated.
|
||||
ba.pushcall(self._check_end_game)
|
||||
|
||||
def _update_scoreboard(self) -> None:
|
||||
for team in self.teams:
|
||||
distances = [player.distance for player in team.players]
|
||||
if not distances:
|
||||
teams_dist = 0.0
|
||||
else:
|
||||
if (isinstance(self.session, ba.DualTeamSession)
|
||||
and self._entire_team_must_finish):
|
||||
teams_dist = min(distances)
|
||||
else:
|
||||
teams_dist = max(distances)
|
||||
self._scoreboard.set_team_value(
|
||||
team,
|
||||
teams_dist,
|
||||
self._laps,
|
||||
flash=(teams_dist >= float(self._laps)),
|
||||
show_value=False)
|
||||
|
||||
def on_begin(self) -> None:
|
||||
from bastd.actor.onscreentimer import OnScreenTimer
|
||||
super().on_begin()
|
||||
self.setup_standard_time_limit(self._time_limit)
|
||||
self.setup_standard_powerup_drops()
|
||||
self._team_finish_pts = 100
|
||||
|
||||
# Throw a timer up on-screen.
|
||||
self._time_text = ba.NodeActor(
|
||||
ba.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, -50),
|
||||
'scale': 1.4,
|
||||
'text': ''
|
||||
}))
|
||||
self._timer = OnScreenTimer()
|
||||
|
||||
if self._mine_spawning != 0:
|
||||
self._race_mines = [
|
||||
RaceMine(point=p, mine=None)
|
||||
for p in self.map.get_def_points('race_mine')
|
||||
]
|
||||
if self._race_mines:
|
||||
self._race_mine_timer = ba.Timer(0.001 * self._mine_spawning,
|
||||
self._update_race_mine,
|
||||
repeat=True)
|
||||
|
||||
self._scoreboard_timer = ba.Timer(0.25,
|
||||
self._update_scoreboard,
|
||||
repeat=True)
|
||||
self._player_order_update_timer = ba.Timer(0.25,
|
||||
self._update_player_order,
|
||||
repeat=True)
|
||||
|
||||
if self.slow_motion:
|
||||
t_scale = 0.4
|
||||
light_y = 50
|
||||
else:
|
||||
t_scale = 1.0
|
||||
light_y = 150
|
||||
lstart = 7.1 * t_scale
|
||||
inc = 1.25 * t_scale
|
||||
|
||||
ba.timer(lstart, self._do_light_1)
|
||||
ba.timer(lstart + inc, self._do_light_2)
|
||||
ba.timer(lstart + 2 * inc, self._do_light_3)
|
||||
ba.timer(lstart + 3 * inc, self._start_race)
|
||||
|
||||
self._start_lights = []
|
||||
for i in range(4):
|
||||
lnub = ba.newnode('image',
|
||||
attrs={
|
||||
'texture': ba.gettexture('nub'),
|
||||
'opacity': 1.0,
|
||||
'absolute_scale': True,
|
||||
'position': (-75 + i * 50, light_y),
|
||||
'scale': (50, 50),
|
||||
'attach': 'center'
|
||||
})
|
||||
ba.animate(
|
||||
lnub, 'opacity', {
|
||||
4.0 * t_scale: 0,
|
||||
5.0 * t_scale: 1.0,
|
||||
12.0 * t_scale: 1.0,
|
||||
12.5 * t_scale: 0.0
|
||||
})
|
||||
ba.timer(13.0 * t_scale, lnub.delete)
|
||||
self._start_lights.append(lnub)
|
||||
|
||||
self._start_lights[0].color = (0.2, 0, 0)
|
||||
self._start_lights[1].color = (0.2, 0, 0)
|
||||
self._start_lights[2].color = (0.2, 0.05, 0)
|
||||
self._start_lights[3].color = (0.0, 0.3, 0)
|
||||
|
||||
def _do_light_1(self) -> None:
|
||||
assert self._start_lights is not None
|
||||
self._start_lights[0].color = (1.0, 0, 0)
|
||||
ba.playsound(self._beep_1_sound)
|
||||
|
||||
def _do_light_2(self) -> None:
|
||||
assert self._start_lights is not None
|
||||
self._start_lights[1].color = (1.0, 0, 0)
|
||||
ba.playsound(self._beep_1_sound)
|
||||
|
||||
def _do_light_3(self) -> None:
|
||||
assert self._start_lights is not None
|
||||
self._start_lights[2].color = (1.0, 0.3, 0)
|
||||
ba.playsound(self._beep_1_sound)
|
||||
|
||||
def _start_race(self) -> None:
|
||||
assert self._start_lights is not None
|
||||
self._start_lights[3].color = (0.0, 1.0, 0)
|
||||
ba.playsound(self._beep_2_sound)
|
||||
for player in self.players:
|
||||
if player.actor is not None:
|
||||
try:
|
||||
assert isinstance(player.actor, PlayerSpaz)
|
||||
player.actor.connect_controls_to_player()
|
||||
except Exception:
|
||||
ba.print_exception('Error in race player connects.')
|
||||
assert self._timer is not None
|
||||
self._timer.start()
|
||||
|
||||
if self._bomb_spawning != 0:
|
||||
self._bomb_spawn_timer = ba.Timer(0.001 * self._bomb_spawning,
|
||||
self._spawn_bomb,
|
||||
repeat=True)
|
||||
|
||||
self._race_started = True
|
||||
|
||||
def _update_player_order(self) -> None:
|
||||
|
||||
# Calc all player distances.
|
||||
for player in self.players:
|
||||
pos: Optional[ba.Vec3]
|
||||
try:
|
||||
pos = player.position
|
||||
except ba.NotFoundError:
|
||||
pos = None
|
||||
if pos is not None:
|
||||
r_index = player.last_region
|
||||
rg1 = self._regions[r_index]
|
||||
r1pt = ba.Vec3(rg1.pos[:3])
|
||||
rg2 = self._regions[0] if r_index == len(
|
||||
self._regions) - 1 else self._regions[r_index + 1]
|
||||
r2pt = ba.Vec3(rg2.pos[:3])
|
||||
r2dist = (pos - r2pt).length()
|
||||
amt = 1.0 - (r2dist / (r2pt - r1pt).length())
|
||||
amt = player.lap + (r_index + amt) * (1.0 / len(self._regions))
|
||||
player.distance = amt
|
||||
|
||||
# Sort players by distance and update their ranks.
|
||||
p_list = [(player.distance, player) for player in self.players]
|
||||
|
||||
p_list.sort(reverse=True, key=lambda x: x[0])
|
||||
for i, plr in enumerate(p_list):
|
||||
plr[1].rank = i
|
||||
if plr[1].actor:
|
||||
node = plr[1].distance_txt
|
||||
if node:
|
||||
node.text = str(i + 1) if plr[1].is_alive() else ''
|
||||
|
||||
def _spawn_bomb(self) -> None:
|
||||
if self._front_race_region is None:
|
||||
return
|
||||
region = (self._front_race_region + 3) % len(self._regions)
|
||||
pos = self._regions[region].pos
|
||||
|
||||
# Don't use the full region so we're less likely to spawn off a cliff.
|
||||
region_scale = 0.8
|
||||
x_range = ((-0.5, 0.5) if pos[3] == 0 else
|
||||
(-region_scale * pos[3], region_scale * pos[3]))
|
||||
z_range = ((-0.5, 0.5) if pos[5] == 0 else
|
||||
(-region_scale * pos[5], region_scale * pos[5]))
|
||||
pos = (pos[0] + random.uniform(*x_range), pos[1] + 1.0,
|
||||
pos[2] + random.uniform(*z_range))
|
||||
ba.timer(random.uniform(0.0, 2.0),
|
||||
ba.WeakCall(self._spawn_bomb_at_pos, pos))
|
||||
|
||||
def _spawn_bomb_at_pos(self, pos: Sequence[float]) -> None:
|
||||
if self.has_ended():
|
||||
return
|
||||
Bomb(position=pos, bomb_type='normal').autoretain()
|
||||
|
||||
def _make_mine(self, i: int) -> None:
|
||||
assert self._race_mines is not None
|
||||
rmine = self._race_mines[i]
|
||||
rmine.mine = Bomb(position=rmine.point[:3], bomb_type='land_mine')
|
||||
rmine.mine.arm()
|
||||
|
||||
def _flash_mine(self, i: int) -> None:
|
||||
assert self._race_mines is not None
|
||||
rmine = self._race_mines[i]
|
||||
light = ba.newnode('light',
|
||||
attrs={
|
||||
'position': rmine.point[:3],
|
||||
'color': (1, 0.2, 0.2),
|
||||
'radius': 0.1,
|
||||
'height_attenuated': False
|
||||
})
|
||||
ba.animate(light, 'intensity', {0.0: 0, 0.1: 1.0, 0.2: 0}, loop=True)
|
||||
ba.timer(1.0, light.delete)
|
||||
|
||||
def _update_race_mine(self) -> None:
|
||||
assert self._race_mines is not None
|
||||
m_index = -1
|
||||
rmine = None
|
||||
for _i in range(3):
|
||||
m_index = random.randrange(len(self._race_mines))
|
||||
rmine = self._race_mines[m_index]
|
||||
if not rmine.mine:
|
||||
break
|
||||
assert rmine is not None
|
||||
if not rmine.mine:
|
||||
self._flash_mine(m_index)
|
||||
ba.timer(0.95, ba.Call(self._make_mine, m_index))
|
||||
|
||||
def spawn_player(self, player: Player) -> ba.Actor:
|
||||
if player.team.finished:
|
||||
# FIXME: This is not type-safe!
|
||||
# This call is expected to always return an Actor!
|
||||
# Perhaps we need something like can_spawn_player()...
|
||||
# noinspection PyTypeChecker
|
||||
return None # type: ignore
|
||||
pos = self._regions[player.last_region].pos
|
||||
|
||||
# Don't use the full region so we're less likely to spawn off a cliff.
|
||||
region_scale = 0.8
|
||||
x_range = ((-0.5, 0.5) if pos[3] == 0 else
|
||||
(-region_scale * pos[3], region_scale * pos[3]))
|
||||
z_range = ((-0.5, 0.5) if pos[5] == 0 else
|
||||
(-region_scale * pos[5], region_scale * pos[5]))
|
||||
pos = (pos[0] + random.uniform(*x_range), pos[1],
|
||||
pos[2] + random.uniform(*z_range))
|
||||
spaz = self.spawn_player_spaz(
|
||||
player, position=pos, angle=270 if not self._race_started else None)
|
||||
assert spaz.node
|
||||
|
||||
# Prevent controlling of characters before the start of the race.
|
||||
if not self._race_started:
|
||||
spaz.disconnect_controls_from_player()
|
||||
|
||||
mathnode = ba.newnode('math',
|
||||
owner=spaz.node,
|
||||
attrs={
|
||||
'input1': (0, 1.4, 0),
|
||||
'operation': 'add'
|
||||
})
|
||||
spaz.node.connectattr('torso_position', mathnode, 'input2')
|
||||
|
||||
distance_txt = ba.newnode('text',
|
||||
owner=spaz.node,
|
||||
attrs={
|
||||
'text': '',
|
||||
'in_world': True,
|
||||
'color': (1, 1, 0.4),
|
||||
'scale': 0.02,
|
||||
'h_align': 'center'
|
||||
})
|
||||
player.distance_txt = distance_txt
|
||||
mathnode.connectattr('output', distance_txt, 'position')
|
||||
return spaz
|
||||
|
||||
def _check_end_game(self) -> None:
|
||||
|
||||
# If there's no teams left racing, finish.
|
||||
teams_still_in = len([t for t in self.teams if not t.finished])
|
||||
if teams_still_in == 0:
|
||||
self.end_game()
|
||||
return
|
||||
|
||||
# Count the number of teams that have completed the race.
|
||||
teams_completed = len(
|
||||
[t for t in self.teams if t.finished and t.time is not None])
|
||||
|
||||
if teams_completed > 0:
|
||||
session = self.session
|
||||
|
||||
# In teams mode its over as soon as any team finishes the race
|
||||
|
||||
# FIXME: The get_ffa_point_awards code looks dangerous.
|
||||
if isinstance(session, ba.DualTeamSession):
|
||||
self.end_game()
|
||||
else:
|
||||
# In ffa we keep the race going while there's still any points
|
||||
# to be handed out. Find out how many points we have to award
|
||||
# and how many teams have finished, and once that matches
|
||||
# we're done.
|
||||
assert isinstance(session, ba.FreeForAllSession)
|
||||
points_to_award = len(session.get_ffa_point_awards())
|
||||
if teams_completed >= points_to_award - teams_completed:
|
||||
self.end_game()
|
||||
return
|
||||
|
||||
def end_game(self) -> None:
|
||||
|
||||
# Stop updating our time text, and set it to show the exact last
|
||||
# finish time if we have one. (so users don't get upset if their
|
||||
# final time differs from what they see onscreen by a tiny amount)
|
||||
assert self._timer is not None
|
||||
if self._timer.has_started():
|
||||
self._timer.stop(
|
||||
endtime=None if self._last_team_time is None else (
|
||||
self._timer.getstarttime() + self._last_team_time))
|
||||
|
||||
results = ba.GameResults()
|
||||
|
||||
for team in self.teams:
|
||||
if team.time is not None:
|
||||
# We store time in seconds, but pass a score in milliseconds.
|
||||
results.set_team_score(team, int(team.time * 1000.0))
|
||||
else:
|
||||
results.set_team_score(team, None)
|
||||
|
||||
# We don't announce a winner in ffa mode since its probably been a
|
||||
# while since the first place guy crossed the finish line so it seems
|
||||
# odd to be announcing that now.
|
||||
self.end(results=results,
|
||||
announce_winning_team=isinstance(self.session,
|
||||
ba.DualTeamSession))
|
||||
|
||||
def handlemessage(self, msg: Any) -> Any:
|
||||
if isinstance(msg, ba.PlayerDiedMessage):
|
||||
# Augment default behavior.
|
||||
super().handlemessage(msg)
|
||||
player = msg.getplayer(Player)
|
||||
if not player.finished:
|
||||
self.respawn_player(player, respawn_time=1)
|
||||
else:
|
||||
super().handlemessage(msg)
|
||||
395
dist/ba_root/mods/games/Tower_Rush.py
vendored
Normal file
395
dist/ba_root/mods/games/Tower_Rush.py
vendored
Normal file
|
|
@ -0,0 +1,395 @@
|
|||
# Released under the MIT License. See LICENSE for details.
|
||||
#
|
||||
"""Defines assault minigame."""
|
||||
|
||||
# ba_meta require api 6
|
||||
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import ba, random
|
||||
from math import cos, sin
|
||||
from bastd.actor.popuptext import PopupText
|
||||
from bastd.actor.powerupbox import PowerupBox, PowerupBoxFactory
|
||||
from bastd.actor.playerspaz import PlayerSpaz
|
||||
from bastd.actor.scoreboard import Scoreboard
|
||||
from bastd.gameutils import SharedObjects
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Type, List, Dict, Sequence, Union
|
||||
|
||||
class Player(ba.Player['Team']):
|
||||
...
|
||||
|
||||
class Team(ba.Team[Player]):
|
||||
def __init__(self) -> None:
|
||||
self.score = 0
|
||||
self.stored_score = 0
|
||||
self.role: str = ''
|
||||
self.spot: str = ''
|
||||
|
||||
|
||||
# ba_meta export game
|
||||
class BaseRaidGame(ba.TeamGameActivity[Player, Team]):
|
||||
|
||||
name = 'Tower Rush'
|
||||
description = """If "score" is shown on your character,\ngo through inside the enemy team's castle-like structure\nto score. Otherwise if "defend" is shown\nprevent the enemy team from entering."""
|
||||
available_settings = [
|
||||
ba.IntSetting('Score to Win Per Team', min_value=1, default=10),
|
||||
ba.IntChoiceSetting('Time Limit',
|
||||
choices=[
|
||||
('None', 0),
|
||||
('1 Minute', 60),
|
||||
('2 Minutes', 120),
|
||||
('5 Minutes', 300),
|
||||
('10 Minutes', 600),
|
||||
('20 Minutes', 1200)],
|
||||
default=300),
|
||||
ba.IntSetting('Countdown Time Each Round', min_value = 10, increment=5 ,default = 60),
|
||||
ba.FloatChoiceSetting(
|
||||
'Respawn Times',
|
||||
choices=[
|
||||
('Shorter', 0.25),
|
||||
('Short', 0.5),
|
||||
('Normal', 1.0),
|
||||
('Long', 2.0),
|
||||
('Longer', 4.0)],
|
||||
default=1.0),
|
||||
ba.BoolSetting('Epic Mode', default=False),
|
||||
ba.BoolSetting('Kill player on ground', default=True),
|
||||
ba.BoolSetting('Random Spawn Point (Team)', default=False),
|
||||
ba.BoolSetting('[On score] Single Teleport', default=True),
|
||||
ba.BoolSetting('[On score] Single Celebrate', default=True)]
|
||||
|
||||
@classmethod
|
||||
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
|
||||
return issubclass(sessiontype, ba.DualTeamSession)
|
||||
|
||||
@classmethod
|
||||
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
|
||||
return ['Tower D']
|
||||
|
||||
def get_instance_scoreboard_display_string(self) -> ba.Lstr:
|
||||
return "Score " + str(self._score_to_win) + " Points"
|
||||
|
||||
def get_instance_description(self) -> Union[str, Sequence]:
|
||||
return "if Score, score by reaching through the foe's structure\nif Defend, prevent enemy from scoring."
|
||||
|
||||
def __init__(self, settings: dict):
|
||||
super().__init__(settings)
|
||||
self.get_s = settings
|
||||
self._scoreboard = Scoreboard()
|
||||
self._last_score_time = 0.0
|
||||
self._score_sound = ba.getsound('score')
|
||||
self._epic_mode = bool(settings['Epic Mode'])
|
||||
self._score_to_win = int(settings['Score to Win Per Team'])
|
||||
self._time_limit = float(settings['Time Limit'])
|
||||
self.time = int(settings['Countdown Time Each Round'])
|
||||
self.change_spawn_points = bool(settings['Random Spawn Point (Team)'])
|
||||
self.ground = bool(settings['Kill player on ground'])
|
||||
self.loop_timer = self.knocker = None
|
||||
|
||||
self.disable_controls = bool(True)
|
||||
|
||||
# Base class overrides
|
||||
self.slow_motion = self._epic_mode
|
||||
self.default_music = (ba.MusicType.EPIC if self._epic_mode else
|
||||
ba.MusicType.FORWARD_MARCH)
|
||||
|
||||
def on_team_join(self, team: Team) -> None:
|
||||
self._update_scoreboard()
|
||||
|
||||
def on_player_join(self, player: PlayerType) -> None:
|
||||
if not self.disable_controls:
|
||||
self.spawn_player(player)
|
||||
else:
|
||||
pass
|
||||
|
||||
def on_begin(self) -> None:
|
||||
super().on_begin()
|
||||
self.setup_standard_powerup_drops()
|
||||
palyer = SharedObjects.get().player_material
|
||||
|
||||
death_material = ba.Material(); box_1 = ba.Material(); box_2 = ba.Material()
|
||||
death_material.add_actions(
|
||||
conditions=('they_have_material', palyer),
|
||||
actions=(('modify_part_collision', 'collide', True),
|
||||
('modify_part_collision', 'physical', False),
|
||||
('call', 'at_connect', ba.WeakCall(self.handle_region, 'ground'))))
|
||||
box_1.add_actions(
|
||||
conditions=('they_have_material', palyer),
|
||||
actions=(('modify_part_collision', 'collide', True),
|
||||
('modify_part_collision', 'physical', False),
|
||||
('call', 'at_connect', ba.WeakCall(self.handle_region, 'turret_1'))))
|
||||
box_2.add_actions(
|
||||
conditions=('they_have_material', palyer),
|
||||
actions=(('modify_part_collision', 'collide', True),
|
||||
('modify_part_collision', 'physical', False),
|
||||
('call', 'at_connect', ba.WeakCall(self.handle_region, 'turret_2'))))
|
||||
|
||||
self.r: List[ba.NodeActor] = []
|
||||
self.r.append(ba.NodeActor(ba.newnode('region',
|
||||
attrs={'position': (-8.450964, 4.784977, 0.300695),
|
||||
'scale': (0.2, 3.45, 1.28),
|
||||
'type': 'box',
|
||||
'materials':[box_1]})))
|
||||
self.r.append(ba.NodeActor(ba.newnode('region',
|
||||
attrs={'position': (7.470666, 3.429754, 0.328592),
|
||||
'scale': (0.2, 2.47, 1.39),
|
||||
'type': 'box',
|
||||
'materials':[box_2]})))
|
||||
if self.ground:
|
||||
self.r.append(ba.NodeActor(ba.newnode('region',
|
||||
attrs={'position': (-0.588583, 1.569668, 4.049047),
|
||||
'scale': (18.0, 0.1, 5.0),
|
||||
'type': 'box',
|
||||
'materials':[death_material]})))
|
||||
self.r.append(ba.NodeActor(ba.newnode('region',
|
||||
attrs={'position': (-0.128583, 1.569668, -1.670954),
|
||||
'scale': (5.0, 0.1, 7.0),
|
||||
'type': 'box',
|
||||
'materials':[death_material]})))
|
||||
|
||||
self.r_timer = ba.newnode('text',
|
||||
attrs={
|
||||
'v_attach': 'top',
|
||||
'h_attach': 'center',
|
||||
'h_align': 'center',
|
||||
'color': (0.7,0.88,1.0,1.1),
|
||||
'shadow': 1.0,
|
||||
'flatness': 1.0,
|
||||
'position': (0, -120),
|
||||
'scale': 1.7,
|
||||
'text': "..."})
|
||||
self.setup_standard_time_limit(self._time_limit)
|
||||
ba.timer(4.5, ba.WeakCall(self.selection, first_run = True))
|
||||
teams = []
|
||||
for t in self.teams:
|
||||
teams.append(t)
|
||||
roles = ['raid', 'defend']
|
||||
if self.change_spawn_points:
|
||||
spots = ['spot2','spot1']
|
||||
|
||||
teams[0].spot = spots[random.randint(0,1)]
|
||||
spots.remove(teams[0].spot)
|
||||
teams[1].spot = spots[0]
|
||||
else:
|
||||
teams[0].spot = 'spot1'
|
||||
teams[1].spot = 'spot2'
|
||||
|
||||
|
||||
teams[0].role = roles[random.randint(0, 1)]
|
||||
roles.remove(teams[0].role)
|
||||
teams[1].role = roles[0]
|
||||
def launch():
|
||||
for t in self.teams:
|
||||
if t.role == 'raid':
|
||||
ba.screenmessage(t.name.evaluate() + " Team, will be the goaler", color=t.color)
|
||||
elif t.role == 'defend':
|
||||
ba.screenmessage(t.name.evaluate() + " Team, will be the defender", color=t.color)
|
||||
ba.timer(1.9, launch)
|
||||
|
||||
def knock_players(self) -> None:
|
||||
for p in self.players:
|
||||
if p.is_alive():
|
||||
p.actor.node.handlemessage('knockout', 800.0)
|
||||
|
||||
def decrease(self) -> None:
|
||||
if int(self.time) != 0:
|
||||
self.time -= 1
|
||||
self.r_timer.text = "Round Time: " + str(self.time)
|
||||
else:
|
||||
self.loop_timer = None
|
||||
self.disable_controls = True
|
||||
self.r_timer.text = "Round Ended"
|
||||
self.knock_players()
|
||||
self.knocker = ba.Timer(0.8, ba.Call(self.knock_players), repeat=True)
|
||||
ba.timer(1, lambda: self.selection())
|
||||
|
||||
def get_pos(self, player: Player, center: bool = False) -> None:
|
||||
|
||||
ang = random.randint(0, 360)
|
||||
rad = random.uniform(0, 2.0) if not center else 0.0
|
||||
y = random.uniform(0.9, 1.16)
|
||||
if player.team.spot == 'spot1':
|
||||
x = cos(ang) * rad
|
||||
z = sin(ang) * rad
|
||||
pos = (-5.786582 + x, 2.8651068 + y, -0.7751054 + z)
|
||||
elif player.team.spot == 'spot2':
|
||||
ang = random.randint(0, 360)
|
||||
rad = random.uniform(0, 2.0)
|
||||
x = cos(ang) * rad
|
||||
z = sin(ang) * rad
|
||||
pos = (4.37031 + x, 2.51977 + y, -0.1901849 + z)
|
||||
return pos
|
||||
|
||||
|
||||
def selection(self, first_run: bool = False) -> None:
|
||||
|
||||
def scene():
|
||||
self.disable_controls = True
|
||||
teams = []
|
||||
for team in self.teams:
|
||||
teams.append(team)
|
||||
|
||||
spots = ['spot1', 'spot2']
|
||||
|
||||
if self.change_spawn_points:
|
||||
teams[0].spot = spots[random.randint(0, 1)]
|
||||
spots.remove(teams[0].spot)
|
||||
teams[1].spot = spots[0]
|
||||
|
||||
if not first_run:
|
||||
temp2 = teams[0].role
|
||||
teams[0].role = teams[1].role
|
||||
|
||||
teams[1].role = temp2
|
||||
|
||||
def func():
|
||||
for t in self.teams:
|
||||
if not first_run:
|
||||
if t.role == 'raid':
|
||||
ba.screenmessage(
|
||||
"It's now " + t.name.evaluate() + " Team's turn, to score. ",
|
||||
color=(0.5, 0.8, 0.8))
|
||||
break
|
||||
ba.timer(0.926, func)
|
||||
|
||||
def scene_2():
|
||||
for t in self.teams:
|
||||
t.stored_score = 0
|
||||
for p in self.players:
|
||||
if p.actor is None:
|
||||
self.spawn_player(p)
|
||||
elif p.is_alive():
|
||||
p.actor.handlemessage(ba.StandMessage(position=self.get_pos(p), angle=random.uniform(0, 360)))
|
||||
|
||||
def delay():
|
||||
for get_s in self.players:
|
||||
if get_s.is_alive():
|
||||
if get_s.team.role == 'raid':
|
||||
PopupText(position=get_s.actor.node.position, text="Score!", color=get_s.team.color, scale=1.5).autoretain()
|
||||
else:
|
||||
PopupText(position=get_s.actor.node.position, text="Defend!", color=get_s.team.color, scale=1.5).autoretain()
|
||||
|
||||
self.r_timer.text = "Round Time: " + str(self.time)
|
||||
self.disable_controls = False
|
||||
def a(): self.knocker = None
|
||||
ba.timer(0.9, a)
|
||||
ba.timer(0.488 if first_run else 0.67, delay)
|
||||
|
||||
self.time = self.get_s['Countdown Time Each Round']
|
||||
self.loop_timer = ba.Timer(1, ba.Call(self.decrease), repeat=True)
|
||||
|
||||
def text():
|
||||
for team in self.teams:
|
||||
if not first_run:
|
||||
if team.role == 'raid':
|
||||
ba.screenmessage(
|
||||
team.name.evaluate() + " Team secured " + str(team.stored_score) + " goals in " + str(self.get_s["Countdown Time Each Round"]) + " seconds.",
|
||||
color=(0.4, 0.6, 1.0)
|
||||
)
|
||||
break
|
||||
|
||||
ba.timer(1.033, text)
|
||||
ba.timer(2, scene)
|
||||
ba.timer(4.858 if not first_run else 3, scene_2)
|
||||
|
||||
def spawn_player(self, player: Player) -> ba.Actor:
|
||||
spaz = self.spawn_player_spaz(player, position=self.get_pos(player))
|
||||
return spaz
|
||||
|
||||
def teleport(self, player: Player) -> None:
|
||||
if self.get_s["[On score] Single Teleport"]:
|
||||
for this in player.team.players:
|
||||
if this.actor:
|
||||
this.actor.handlemessage(ba.StandMessage(position=self.get_pos(this), angle=random.uniform(0, 360)))
|
||||
else:
|
||||
if player.actor:
|
||||
player.actor.handlemessage(ba.StandMessage(position=self.get_pos(player), angle=random.uniform(0, 360)))
|
||||
|
||||
if self.get_s['[On score] Single Celebrate']:
|
||||
for this in player.team.players:
|
||||
if this.actor:
|
||||
this.actor.handlemessage(ba.CelebrateMessage(2.0))
|
||||
else:
|
||||
if player.actor:
|
||||
player.actor.handlemessage(ba.CelebrateMessage(2.0))
|
||||
self.stats.player_scored(player, 10, big_message=True)
|
||||
|
||||
def handle_region(self, region: str) -> None:
|
||||
try:
|
||||
player = ba.getcollision().opposingnode.getdelegate(
|
||||
PlayerSpaz, True).getplayer(Player, True)
|
||||
except: return
|
||||
|
||||
if region == 'ground' and not self.disable_controls:
|
||||
def delay():
|
||||
player.actor.handlemessage(ba.DieMessage())
|
||||
ba.timer(10*0.001, delay)
|
||||
|
||||
elif region == 'turret_2':
|
||||
if player.is_alive():
|
||||
if player.team.role == 'raid' and player.team.spot != 'spot2':
|
||||
if ba.time() != self._last_score_time:
|
||||
self._last_score_time = ba.time()
|
||||
ba.playsound(self._score_sound)
|
||||
player.team.score += 1
|
||||
player.team.stored_score += 1
|
||||
self._update_scoreboard()
|
||||
self.teleport(player)
|
||||
else:
|
||||
return
|
||||
|
||||
elif region == 'turret_1':
|
||||
if player.is_alive():
|
||||
if player.team.role == 'raid' and player.team.spot != 'spot1':
|
||||
if ba.time() != self._last_score_time:
|
||||
self._last_score_time = ba.time()
|
||||
ba.playsound(self._score_sound)
|
||||
player.team.score += 1
|
||||
player.team.stored_score += 1
|
||||
self._update_scoreboard()
|
||||
self.teleport(player)
|
||||
|
||||
def _standard_drop_powerup(self, index: int, expire: bool = True) -> None:
|
||||
self.i = [(6.1527314, 4.9323297, -7.8393626),
|
||||
(-6.8911242, 4.4702456, -7.8909187),
|
||||
(-5.3111238, 3.930246, -6.170918),
|
||||
(3.9788754, 3.8102467, -5.9009175),
|
||||
(-4.926642821, 2.397645612, 2.876782366),
|
||||
(-1.964335546, 2.397645612, 3.751374716),
|
||||
(1.64883201, 2.397645612, 3.751374716),
|
||||
(4.398865293, 2.397645612, 2.877618924)]
|
||||
self.i = ([p[:3] for p in self.i])
|
||||
PowerupBox(
|
||||
position=self.i[index],
|
||||
poweruptype=PowerupBoxFactory.get().get_random_powerup_type(),
|
||||
expire=expire).autoretain()
|
||||
|
||||
def _standard_drop_powerups(self) -> None:
|
||||
for i in range(4 if self.ground else 8):
|
||||
ba.timer(i * 0.4, ba.WeakCall(self._standard_drop_powerup, i))
|
||||
|
||||
def handlemessage(self, msg: Any) -> Any:
|
||||
if isinstance(msg, ba.PlayerDiedMessage):
|
||||
self.respawn_player(msg.getplayer(Player))
|
||||
else:
|
||||
super().handlemessage(msg)
|
||||
return None
|
||||
|
||||
def end_game(self) -> None:
|
||||
self.loop_timer = self.knocker = None
|
||||
results = ba.GameResults()
|
||||
for team in self.teams:
|
||||
results.set_team_score(team, team.score)
|
||||
self.end(results=results)
|
||||
|
||||
def _update_scoreboard(self) -> None:
|
||||
for team in self.teams:
|
||||
self._scoreboard.set_team_value(team, team.score,
|
||||
self._score_to_win)
|
||||
if team.score >= self._score_to_win:
|
||||
self.end_game()
|
||||
537
dist/ba_root/mods/games/VolleyBall.py
vendored
Normal file
537
dist/ba_root/mods/games/VolleyBall.py
vendored
Normal file
|
|
@ -0,0 +1,537 @@
|
|||
from __future__ import annotations
|
||||
|
||||
#Volley Ball (updated)
|
||||
#Made for 1.6 by your friend: @[Just] Freak#4999
|
||||
|
||||
"""Defines Volley Ball mini-game"""
|
||||
|
||||
|
||||
|
||||
|
||||
## This thing was originally made for 1.4 by someone (but had errors/bugs/missing features) so I edited/ported to 1.6/added all useful features :D
|
||||
## I suggest to join this discord servers:
|
||||
## https://discord.gg/ucyaesh
|
||||
## https://discord.gg/NCvfPG2N9A
|
||||
|
||||
|
||||
## Made on Android with the help of Terminal.py
|
||||
## https://github.com/FreakOPP/BombSquad-Mods-byFREAK/blob/main/Utilities/Terminal.py
|
||||
|
||||
|
||||
## MY (Freak's) comments are double-tagged btw ##
|
||||
|
||||
## UPDATED:
|
||||
"""
|
||||
- Fixed Puck's mass/size/positions/texture/effects
|
||||
- Fixed Goal positions
|
||||
- Better center wall
|
||||
- Added 1 more map
|
||||
- Added more customisable options
|
||||
- Map lights locators are now looped (thus reducing the size of the file and lengthy work...)
|
||||
- Merged map & minigame in one file
|
||||
- Puck spawns according to scored team (if right team scored, ball will spawn on left side)
|
||||
- Also puck now spawns in airrr
|
||||
- Server support added :)
|
||||
- Fixed **LOTS** of errors/bugs
|
||||
"""
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# ba_meta require api 6
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import bastd, _ba, ba, random
|
||||
from bastd.actor.playerspaz import PlayerSpaz
|
||||
from bastd.actor.scoreboard import Scoreboard
|
||||
from bastd.actor.powerupbox import PowerupBoxFactory
|
||||
from bastd.gameutils import SharedObjects
|
||||
|
||||
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
|
||||
|
||||
|
||||
class Puck(ba.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.8, position[2])
|
||||
self.last_players_to_touch: Dict[int, Player] = {}
|
||||
self.scored = False
|
||||
assert activity is not None
|
||||
assert isinstance(activity, VolleyBallGame)
|
||||
pmats = [shared.object_material, activity.puck_material]
|
||||
self.node = ba.newnode('prop',
|
||||
delegate=self,
|
||||
attrs={
|
||||
'model': activity.puck_model,
|
||||
'color_texture': activity.puck_tex,
|
||||
'body': 'sphere',
|
||||
'reflection': 'soft',
|
||||
'reflection_scale': [0.2],
|
||||
'shadow_size': 0.6,
|
||||
'model_scale': 0.4,
|
||||
'body_scale': 1.07,
|
||||
'is_area_of_interest': True,
|
||||
'position': self._spawn_pos,
|
||||
'materials': pmats
|
||||
})
|
||||
|
||||
## Since it rolls on spawn, lets make gravity
|
||||
## to 0, and when another node (bomb/spaz)
|
||||
## touches it. It'll act back as our normie puck!
|
||||
ba.animate(self.node, 'gravity_scale', {0:-0.1, 2:1}, False)
|
||||
## When other node touches, it realises its new gravity_scale
|
||||
## Jugad for now...
|
||||
|
||||
|
||||
|
||||
|
||||
def handlemessage(self, msg: Any) -> Any:
|
||||
if isinstance(msg, ba.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, ba.OutOfBoundsMessage):
|
||||
assert self.node
|
||||
self.node.position = self._spawn_pos
|
||||
|
||||
elif isinstance(msg, ba.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(ba.Player['Team']):
|
||||
"""Our player type for this game."""
|
||||
|
||||
|
||||
class Team(ba.Team[Player]):
|
||||
"""Our team type for this game."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.score = 0
|
||||
|
||||
|
||||
# ba_meta export game
|
||||
class VolleyBallGame(ba.TeamGameActivity[Player, Team]):
|
||||
"""Volley Ball game."""
|
||||
|
||||
name = 'Volley Ball'
|
||||
description = 'Score some goals.\nbyFREAK'
|
||||
available_settings = [
|
||||
ba.IntSetting(
|
||||
'Score to Win',
|
||||
min_value=1,
|
||||
default=1,
|
||||
increment=1,
|
||||
),
|
||||
ba.IntChoiceSetting(
|
||||
'Time Limit',
|
||||
choices=[
|
||||
('None', 0),
|
||||
('1 Minute', 60),
|
||||
('2 Minutes', 120),
|
||||
('5 Minutes', 300),
|
||||
('10 Minutes', 600),
|
||||
('20 Minutes', 1200),
|
||||
],
|
||||
default=0,
|
||||
),
|
||||
ba.FloatChoiceSetting(
|
||||
'Respawn Times',
|
||||
choices=[
|
||||
('Shorter', 0.25),
|
||||
('Short', 0.5),
|
||||
('Normal', 1.0),
|
||||
('Long', 2.0),
|
||||
('Longer', 4.0),
|
||||
],
|
||||
default=1.0,
|
||||
),
|
||||
ba.BoolSetting('Epic Mode', True),
|
||||
ba.BoolSetting('Night Mode', False),
|
||||
ba.BoolSetting('Icy Floor', True),
|
||||
ba.BoolSetting('Disable Punch', False),
|
||||
ba.BoolSetting('Disable Bombs', False),
|
||||
ba.BoolSetting('Enable Bottom Credits', True),
|
||||
]
|
||||
default_music = ba.MusicType.HOCKEY
|
||||
|
||||
@classmethod
|
||||
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
|
||||
return issubclass(sessiontype, ba.DualTeamSession)
|
||||
|
||||
@classmethod
|
||||
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
|
||||
return ['Open Field','Closed Arena']
|
||||
|
||||
def __init__(self, settings: dict):
|
||||
super().__init__(settings)
|
||||
shared = SharedObjects.get()
|
||||
self._scoreboard = Scoreboard()
|
||||
self._cheer_sound = ba.getsound('cheer')
|
||||
self._chant_sound = ba.getsound('crowdChant')
|
||||
self._foghorn_sound = ba.getsound('foghorn')
|
||||
self._swipsound = ba.getsound('swip')
|
||||
self._whistle_sound = ba.getsound('refWhistle')
|
||||
self.puck_model = ba.getmodel('shield')
|
||||
self.puck_tex = ba.gettexture('gameCircleIcon')
|
||||
self._puck_sound = ba.getsound('metalHit')
|
||||
self.puck_material = ba.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', ba.DieMessage())))
|
||||
self._score_region_material = ba.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._wall_material=ba.Material()
|
||||
self._fake_wall_material=ba.Material()
|
||||
self._wall_material.add_actions(
|
||||
|
||||
actions=(
|
||||
('modify_part_collision', 'friction', 100000),
|
||||
))
|
||||
self._wall_material.add_actions(
|
||||
conditions=('they_have_material', shared.pickup_material),
|
||||
actions=(
|
||||
('modify_part_collision', 'collide', False),
|
||||
))
|
||||
|
||||
self._wall_material.add_actions(
|
||||
conditions=(('we_are_younger_than', 100),
|
||||
'and',
|
||||
('they_have_material',shared.object_material)),
|
||||
actions=(
|
||||
('modify_part_collision', 'collide', False),
|
||||
))
|
||||
self._wall_material.add_actions(
|
||||
conditions=('they_have_material',shared.footing_material),
|
||||
actions=(
|
||||
('modify_part_collision', 'friction', 9999.5),
|
||||
))
|
||||
self._wall_material.add_actions(
|
||||
conditions=('they_have_material', bastd.actor.bomb.BombFactory.get().blast_material),
|
||||
actions=(
|
||||
('modify_part_collision', 'collide', False),
|
||||
('modify_part_collision', 'physical', False)
|
||||
|
||||
))
|
||||
self._fake_wall_material.add_actions(
|
||||
conditions=('they_have_material', shared.player_material),
|
||||
actions=(
|
||||
('modify_part_collision', 'collide', True),
|
||||
('modify_part_collision', 'physical', True)
|
||||
|
||||
))
|
||||
self.blocks=[]
|
||||
|
||||
|
||||
self._net_wall_material=ba.Material()
|
||||
self._net_wall_material.add_actions(
|
||||
conditions=('they_have_material', shared.player_material),
|
||||
actions=(
|
||||
('modify_part_collision', 'collide', True),
|
||||
('modify_part_collision', 'physical', True)
|
||||
|
||||
))
|
||||
|
||||
self._net_wall_material.add_actions(
|
||||
conditions=('they_have_material', shared.object_material),
|
||||
actions=(
|
||||
('modify_part_collision', 'collide', True),
|
||||
))
|
||||
self._net_wall_material.add_actions(
|
||||
conditions=('they_have_material', self.puck_material),
|
||||
actions=(
|
||||
('modify_part_collision', 'collide', True),
|
||||
))
|
||||
self._net_wall_material.add_actions(
|
||||
conditions=('we_are_older_than', 1),
|
||||
actions=(
|
||||
('modify_part_collision', 'collide', True),
|
||||
))
|
||||
self.net_blocc=[]
|
||||
|
||||
|
||||
self._puck_spawn_pos: Optional[Sequence[float]] = None
|
||||
self._score_regions: Optional[List[ba.NodeActor]] = None
|
||||
self._puck: Optional[Puck] = None
|
||||
self._score_to_win = int(settings['Score to Win'])
|
||||
self._punchie_ = bool(settings['Disable Punch'])
|
||||
self._night_mode = bool(settings['Night Mode'])
|
||||
self._bombies_ = bool(settings['Disable Bombs'])
|
||||
self._time_limit = float(settings['Time Limit'])
|
||||
self._icy_flooor = bool(settings['Icy Floor'])
|
||||
self.credit_text = bool(settings['Enable Bottom Credits'])
|
||||
self._epic_mode = bool(settings['Epic Mode'])
|
||||
# Base class overrides.
|
||||
self.slow_motion = self._epic_mode
|
||||
self.default_music = (ba.MusicType.EPIC if self._epic_mode else
|
||||
ba.MusicType.TO_THE_DEATH)
|
||||
|
||||
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)
|
||||
if self._night_mode:
|
||||
ba.getactivity().globalsnode.tint = (0.5, 0.7, 1)
|
||||
else:
|
||||
pass
|
||||
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(
|
||||
ba.NodeActor(
|
||||
ba.newnode('region',
|
||||
attrs={
|
||||
'position':(5,0,0),
|
||||
'scale': defs.boxes['goal1'],
|
||||
'type': 'box',
|
||||
'materials': [self._score_region_material]
|
||||
})))
|
||||
self._score_regions.append(
|
||||
ba.NodeActor(
|
||||
ba.newnode('region',
|
||||
attrs={
|
||||
'position':(-5,0,0),
|
||||
'scale': defs.boxes['goal2'],
|
||||
'type': 'box',
|
||||
'materials': [self._score_region_material]
|
||||
})))
|
||||
self._update_scoreboard()
|
||||
ba.playsound(self._chant_sound)
|
||||
import base64
|
||||
exec(base64.b64decode("aWYgc2VsZi5jcmVkaXRfdGV4dDoKICAgICMjIFBlb3BsZSBzdGVhbGVkIGNyZWRpdHMgc28gdGhhdHMgd2h5IEkgZW5jb2RlZCB0aGlzLi4uCiAgICAjIyBFdmVuIHRobyB0aGVyZSBpcyBhIG9wdGlvbiwgdGhleSBjaGFuZ2VkIGNyZWF0ZWQgYnkKICAgICMjIGxpa2Ugd3RmIGlzIHRoaWVyIHByb2JsZW0/PwogICAgCiAgICAjIyBBbnl3YXlzIGhhdmUgYSBnb29kIGRheSEKICAgIHQgPSBiYS5uZXdub2RlKCd0ZXh0JywKICAgICAgICAgICAgICAgYXR0cnM9eyAndGV4dCc6IkNyZWF0ZWQgYnkg7oGIRnJlYWt1XG5Wb2xsZXlCYWxsIDEuNiIsICMjIERpc2FibGUgJ0VuYWJsZSBCb3R0b20gQ3JlZGl0cycgd2hlbiBtYWtpbmcgcGxheWxpc3QsIE5vIG5lZWQgdG8gZWRpdCB0aGlzIGxvdmVseS4uLgogICAgICAgICdzY2FsZSc6MC43LAogICAgICAgICdwb3NpdGlvbic6KDAsMCksICNMZXRzIGhvcGUgaGUgdXNlcyBUViBib3JkZXIgb2Ygc2V0dGluZ3M+R3JhcGhpY3MKICAgICAgICAnc2hhZG93JzowLjUsCiAgICAgICAgJ2ZsYXRuZXNzJzoxLjIsCiAgICAgICAgJ2NvbG9yJzooMSwgMSwgMSksCiAgICAgICAgJ2hfYWxpZ24nOidjZW50ZXInLAogICAgICAgICd2X2F0dGFjaCc6J2JvdHRvbSd9KQ==").decode('UTF-8'))
|
||||
shared = SharedObjects.get()
|
||||
self.blocks.append(ba.NodeActor(ba.newnode('region',attrs={'position': (0,2.4,0),'scale': (1,6,20),'type': 'box','materials': (self._fake_wall_material, )})))
|
||||
|
||||
self.net_blocc.append(ba.NodeActor(ba.newnode('region',attrs={'position': (0,0,0),'scale': (0.6,2.4,20),'type': 'box','materials': (self._net_wall_material, )})))
|
||||
|
||||
def on_team_join(self, team: Team) -> None:
|
||||
self._update_scoreboard()
|
||||
|
||||
def _handle_puck_player_collide(self) -> None:
|
||||
collision = ba.getcollision()
|
||||
try:
|
||||
puck = collision.sourcenode.getdelegate(Puck, True)
|
||||
player = collision.opposingnode.getdelegate(PlayerSpaz,
|
||||
True).getplayer(
|
||||
Player, True)
|
||||
except ba.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 = ba.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
|
||||
|
||||
|
||||
|
||||
## Spawn puck on opponent's Area
|
||||
if team.id == 0: # left side scored
|
||||
self._puck_spawn_pos= (5, -0.3, 0)
|
||||
elif team.id == 1: # right side scored
|
||||
self._puck_spawn_pos= (-5, -0.3, 0)
|
||||
else: # incase, this dude is oversmart and using 3+ teams...
|
||||
self._puck_spawn_pos= (0, 0.2, 0)
|
||||
## Easy pizzy
|
||||
|
||||
|
||||
for player in team.players:
|
||||
if player.actor:
|
||||
player.actor.handlemessage(ba.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],
|
||||
50,
|
||||
big_message=True)
|
||||
|
||||
# End game if we won.
|
||||
if team.score >= self._score_to_win:
|
||||
self.end_game()
|
||||
|
||||
ba.playsound(self._foghorn_sound)
|
||||
ba.playsound(self._cheer_sound)
|
||||
|
||||
self._puck.scored = True
|
||||
|
||||
# Kill the puck (it'll respawn itself shortly).
|
||||
ba.emitfx(position= ba.getcollision().position, count=int(6.0 + 7.0 * 12), scale=3, spread=0.5, chunk_type='spark')
|
||||
ba.timer(0.7, self._kill_puck)
|
||||
|
||||
|
||||
ba.cameraflash(duration=7.0)
|
||||
self._update_scoreboard()
|
||||
|
||||
def end_game(self) -> None:
|
||||
results = ba.GameResults()
|
||||
for team in self.teams:
|
||||
results.set_team_score(team, team.score)
|
||||
self.end(results=results)
|
||||
|
||||
def on_transition_in(self) -> None:
|
||||
super().on_transition_in()
|
||||
activity = ba.getactivity()
|
||||
if self._icy_flooor:
|
||||
activity.map.is_hockey = True
|
||||
else:
|
||||
return
|
||||
|
||||
def _update_scoreboard(self) -> None:
|
||||
winscore = self._score_to_win
|
||||
for team in self.teams:
|
||||
self._scoreboard.set_team_value(team, team.score, winscore)
|
||||
|
||||
# overriding the default character spawning..
|
||||
def spawn_player(self, player: Player) -> ba.Actor:
|
||||
spaz = self.spawn_player_spaz(player)
|
||||
|
||||
if self._bombies_:
|
||||
## We wantthe button to work, justno bombs...
|
||||
spaz.bomb_count = 0
|
||||
## Imagine not being able to swipe those colorful buttons ;(
|
||||
|
||||
|
||||
if self._punchie_:
|
||||
spaz.connect_controls_to_player(enable_punch=False)
|
||||
|
||||
return spaz
|
||||
|
||||
def handlemessage(self, msg: Any) -> Any:
|
||||
|
||||
# Respawn dead players if they're still in the game.
|
||||
if isinstance(msg, ba.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():
|
||||
ba.timer(2.2, self._spawn_puck)
|
||||
else:
|
||||
super().handlemessage(msg)
|
||||
|
||||
def _flash_puck_spawn(self) -> None:
|
||||
## Effect >>>>>> Flashly
|
||||
ba.emitfx(position= self._puck_spawn_pos, count=int(6.0 + 7.0 * 12), scale=1.7, spread=0.4, chunk_type='spark')
|
||||
|
||||
def _spawn_puck(self) -> None:
|
||||
ba.playsound(self._swipsound)
|
||||
ba.playsound(self._whistle_sound)
|
||||
self._flash_puck_spawn()
|
||||
assert self._puck_spawn_pos is not None
|
||||
self._puck = Puck(position=self._puck_spawn_pos)
|
||||
|
||||
673
dist/ba_root/mods/games/baBasketBomb.py
vendored
Normal file
673
dist/ba_root/mods/games/baBasketBomb.py
vendored
Normal file
|
|
@ -0,0 +1,673 @@
|
|||
# Released under the MIT License. See LICENSE for details.
|
||||
# ba_meta require api 6
|
||||
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import ba, _ba
|
||||
from bastd.actor.playerspaz import PlayerSpaz
|
||||
from bastd.actor.scoreboard import Scoreboard
|
||||
from bastd.actor.powerupbox import PowerupBoxFactory
|
||||
from bastd.gameutils import SharedObjects
|
||||
from bastd.actor import playerspaz as ps
|
||||
from bastd import maps
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Sequence, Dict, Type, List, Optional, Union
|
||||
|
||||
bsuSpaz = None
|
||||
|
||||
def getlanguage(text, sub: str = ''):
|
||||
lang = _ba.app.lang.language
|
||||
translate = {
|
||||
"Name":
|
||||
{"Spanish": "Baloncesto",
|
||||
"English": "Basketbomb",
|
||||
"Portuguese": "Basketbomb"},
|
||||
"Info":
|
||||
{"Spanish": "Anota todas las canastas y sé el MVP.",
|
||||
"English": "Score all the baskets and be the MVP.",
|
||||
"Portuguese": "Marque cada cesta e seja o MVP."},
|
||||
"Info-Short":
|
||||
{"Spanish": f"Anota {sub} canasta(s) para ganar",
|
||||
"English": f"Score {sub} baskets to win",
|
||||
"Portuguese": f"Cestas de {sub} pontos para ganhar"},
|
||||
"S: Powerups":
|
||||
{"Spanish": "Aparecer Potenciadores",
|
||||
"English": "Powerups Spawn",
|
||||
"Portuguese": "Habilitar Potenciadores"},
|
||||
"S: Velocity":
|
||||
{"Spanish": "Activar velocidad",
|
||||
"English": "Enable speed",
|
||||
"Portuguese": "Ativar velocidade"},
|
||||
}
|
||||
|
||||
languages = ['Spanish','Portuguese','English']
|
||||
if lang not in languages: lang = 'English'
|
||||
|
||||
if text not in translate:
|
||||
return text
|
||||
return translate[text][lang]
|
||||
|
||||
class BallDiedMessage:
|
||||
def __init__(self, ball: Ball):
|
||||
self.ball = ball
|
||||
|
||||
class Ball(ba.Actor):
|
||||
def __init__(self, position: Sequence[float] = (0.0, 1.0, 0.0)):
|
||||
super().__init__()
|
||||
shared = SharedObjects.get()
|
||||
activity = self.getactivity()
|
||||
velocty = (0.0, 8.0, 0.0)
|
||||
_scale = 1.2
|
||||
|
||||
self._spawn_pos = (position[0], position[1] + 0.5, position[2])
|
||||
self.last_players_to_touch: Dict[int, Player] = {}
|
||||
self.scored = False
|
||||
|
||||
assert activity is not None
|
||||
assert isinstance(activity, BasketGame)
|
||||
|
||||
pmats = [shared.object_material, activity.ball_material]
|
||||
self.node = ba.newnode('prop',
|
||||
delegate=self,
|
||||
attrs={
|
||||
'model': activity.ball_model,
|
||||
'color_texture': activity.ball_tex,
|
||||
'body': 'sphere',
|
||||
'reflection': 'soft',
|
||||
'body_scale': 1.0 * _scale,
|
||||
'reflection_scale': [1.3],
|
||||
'shadow_size': 1.0,
|
||||
'gravity_scale': 0.92,
|
||||
'density': max(0.4 * _scale, 0.3),
|
||||
'position': self._spawn_pos,
|
||||
'velocity': velocty,
|
||||
'materials': pmats})
|
||||
self.scale = scale = 0.25 * _scale
|
||||
ba.animate(self.node, 'model_scale', {0: 0, 0.2: scale*1.3, 0.26: scale})
|
||||
|
||||
def handlemessage(self, msg: Any) -> Any:
|
||||
if isinstance(msg, ba.DieMessage):
|
||||
assert self.node
|
||||
self.node.delete()
|
||||
activity = self._activity()
|
||||
if activity and not msg.immediate:
|
||||
activity.handlemessage(BallDiedMessage(self))
|
||||
|
||||
elif isinstance(msg, ba.OutOfBoundsMessage):
|
||||
assert self.node
|
||||
self.node.position = self._spawn_pos
|
||||
self.node.velocity = (0.0, 0.0, 0.0)
|
||||
|
||||
elif isinstance(msg, ba.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])
|
||||
|
||||
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(ba.Player['Team']):
|
||||
"""Our player type for this game."""
|
||||
|
||||
|
||||
class Team(ba.Team[Player]):
|
||||
"""Our team type for this game."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.score = 0
|
||||
|
||||
class Points:
|
||||
postes = dict()
|
||||
postes['pal_0'] = (10.64702320098877, 0.0000000000000000, 0.0000000000000000) #10.736066818237305, 0.3002409040927887, 0.5281256437301636
|
||||
postes['pal_1'] = (-10.64702320098877, 0.0000000000000000, 0.0000000000000000)
|
||||
|
||||
# ba_meta export game
|
||||
class BasketGame(ba.TeamGameActivity[Player, Team]):
|
||||
|
||||
name = getlanguage('Name')
|
||||
description = getlanguage('Info')
|
||||
available_settings = [
|
||||
ba.IntSetting(
|
||||
'Score to Win',
|
||||
min_value=1,
|
||||
default=1,
|
||||
increment=1,
|
||||
),
|
||||
ba.IntChoiceSetting(
|
||||
'Time Limit',
|
||||
choices=[
|
||||
('None', 0),
|
||||
('1 Minute', 60),
|
||||
('2 Minutes', 120),
|
||||
('5 Minutes', 300),
|
||||
('10 Minutes', 600),
|
||||
('20 Minutes', 1200),
|
||||
],
|
||||
default=0,
|
||||
),
|
||||
ba.FloatChoiceSetting(
|
||||
'Respawn Times',
|
||||
choices=[
|
||||
('Shorter', 0.25),
|
||||
('Short', 0.5),
|
||||
('Normal', 1.0),
|
||||
('Long', 2.0),
|
||||
('Longer', 4.0),
|
||||
],
|
||||
default=1.0,
|
||||
),
|
||||
ba.BoolSetting(getlanguage('S: Powerups'), default=True),
|
||||
ba.BoolSetting(getlanguage('S: Velocity'), default=False),
|
||||
ba.BoolSetting('Epic Mode', default=False),
|
||||
]
|
||||
default_music = ba.MusicType.HOCKEY
|
||||
|
||||
@classmethod
|
||||
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
|
||||
return issubclass(sessiontype, ba.DualTeamSession)
|
||||
|
||||
@classmethod
|
||||
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
|
||||
return ['BasketBall Stadium', 'BasketBall Stadium V2']
|
||||
|
||||
def __init__(self, settings: dict):
|
||||
super().__init__(settings)
|
||||
shared = SharedObjects.get()
|
||||
self._scoreboard = Scoreboard()
|
||||
self._cheer_sound = ba.getsound('cheer')
|
||||
self._chant_sound = ba.getsound('crowdChant')
|
||||
self._foghorn_sound = ba.getsound('foghorn')
|
||||
self._swipsound = ba.getsound('swip')
|
||||
self._whistle_sound = ba.getsound('refWhistle')
|
||||
self.ball_model = ba.getmodel('shield')
|
||||
self.ball_tex = ba.gettexture('fontExtras3')
|
||||
self._ball_sound = ba.getsound('bunnyJump')
|
||||
self._powerups = bool(settings[getlanguage('S: Powerups')])
|
||||
self._speed = bool(settings[getlanguage('S: Velocity')])
|
||||
self._epic_mode = bool(settings['Epic Mode'])
|
||||
self.slow_motion = self._epic_mode
|
||||
|
||||
self.ball_material = ba.Material()
|
||||
self.ball_material.add_actions(actions=(('modify_part_collision',
|
||||
'friction', 0.5)))
|
||||
self.ball_material.add_actions(conditions=('they_have_material',
|
||||
shared.pickup_material),
|
||||
actions=('modify_part_collision',
|
||||
'collide', True))
|
||||
self.ball_material.add_actions(
|
||||
conditions=(
|
||||
('we_are_younger_than', 100),
|
||||
'and',
|
||||
('they_have_material', shared.object_material),
|
||||
),
|
||||
actions=('modify_node_collision', 'collide', False),
|
||||
)
|
||||
self.ball_material.add_actions(conditions=('they_have_material',
|
||||
shared.footing_material),
|
||||
actions=('impact_sound',
|
||||
self._ball_sound, 0.2, 5))
|
||||
|
||||
# Keep track of which player last touched the ball
|
||||
self.ball_material.add_actions(
|
||||
conditions=('they_have_material', shared.player_material),
|
||||
actions=(('call', 'at_connect',
|
||||
self._handle_ball_player_collide), ))
|
||||
|
||||
self._score_region_material = ba.Material()
|
||||
self._score_region_material.add_actions(
|
||||
conditions=('they_have_material', self.ball_material),
|
||||
actions=(('modify_part_collision', 'collide',
|
||||
True), ('modify_part_collision', 'physical', False),
|
||||
('call', 'at_connect', self._handle_score)))
|
||||
self._ball_spawn_pos: Optional[Sequence[float]] = None
|
||||
self._score_regions: Optional[List[ba.NodeActor]] = None
|
||||
self._ball: Optional[Ball] = 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]:
|
||||
return getlanguage('Info-Short', sub=self._score_to_win)
|
||||
|
||||
def get_instance_description_short(self) -> Union[str, Sequence]:
|
||||
return getlanguage('Info-Short', sub=self._score_to_win)
|
||||
|
||||
def on_begin(self) -> None:
|
||||
super().on_begin()
|
||||
|
||||
self.setup_standard_time_limit(self._time_limit)
|
||||
|
||||
if self._powerups:
|
||||
self.setup_standard_powerup_drops()
|
||||
|
||||
self._ball_spawn_pos = self.map.get_flag_position(None)
|
||||
self._spawn_ball()
|
||||
|
||||
defs = self.map.defs
|
||||
self._score_regions = []
|
||||
self._score_regions.append(
|
||||
ba.NodeActor(
|
||||
ba.newnode('region',
|
||||
attrs={
|
||||
'position': defs.boxes['goal1'][0:3],
|
||||
'scale': defs.boxes['goal1'][6:9],
|
||||
'type': 'box',
|
||||
'materials': []
|
||||
})))
|
||||
self._score_regions.append(
|
||||
ba.NodeActor(
|
||||
ba.newnode('region',
|
||||
attrs={
|
||||
'position': defs.boxes['goal2'][0:3],
|
||||
'scale': defs.boxes['goal2'][6:9],
|
||||
'type': 'box',
|
||||
'materials': []
|
||||
})))
|
||||
self._update_scoreboard()
|
||||
ba.playsound(self._chant_sound)
|
||||
|
||||
for id, team in enumerate(self.teams):
|
||||
self.postes(id)
|
||||
|
||||
def on_team_join(self, team: Team) -> None:
|
||||
self._update_scoreboard()
|
||||
|
||||
def _handle_ball_player_collide(self) -> None:
|
||||
collision = ba.getcollision()
|
||||
try:
|
||||
ball = collision.sourcenode.getdelegate(Ball, True)
|
||||
player = collision.opposingnode.getdelegate(PlayerSpaz,
|
||||
True).getplayer(
|
||||
Player, True)
|
||||
except ba.NotFoundError:
|
||||
return
|
||||
|
||||
ball.last_players_to_touch[player.team.id] = player
|
||||
|
||||
def _kill_ball(self) -> None:
|
||||
self._ball = None
|
||||
|
||||
def _handle_score(self, team_index: int = None) -> None:
|
||||
assert self._ball is not None
|
||||
assert self._score_regions is not None
|
||||
|
||||
if self._ball.scored:
|
||||
return
|
||||
|
||||
region = ba.getcollision().sourcenode
|
||||
index = 0
|
||||
for index in range(len(self._score_regions)):
|
||||
if region == self._score_regions[index].node:
|
||||
break
|
||||
|
||||
if team_index is not None:
|
||||
index = team_index
|
||||
|
||||
for team in self.teams:
|
||||
if team.id == index:
|
||||
scoring_team = team
|
||||
team.score += 1
|
||||
|
||||
for player in team.players:
|
||||
if player.actor:
|
||||
player.actor.handlemessage(ba.CelebrateMessage(2.0))
|
||||
|
||||
if (scoring_team.id in self._ball.last_players_to_touch
|
||||
and self._ball.last_players_to_touch[scoring_team.id]):
|
||||
self.stats.player_scored(
|
||||
self._ball.last_players_to_touch[scoring_team.id],
|
||||
100, big_message=True)
|
||||
|
||||
if team.score >= self._score_to_win:
|
||||
self.end_game()
|
||||
|
||||
#ba.playsound(self._foghorn_sound)
|
||||
ba.playsound(self._cheer_sound)
|
||||
|
||||
self._ball.scored = True
|
||||
|
||||
# Kill the ball (it'll respawn itself shortly).
|
||||
ba.timer(1.0, self._kill_ball)
|
||||
|
||||
light = ba.newnode('light',
|
||||
attrs={
|
||||
'position': ba.getcollision().position,
|
||||
'height_attenuated': False,
|
||||
'color': (1, 0, 0)
|
||||
})
|
||||
ba.animate(light, 'intensity', {0: 0, 0.5: 1, 1.0: 0}, loop=True)
|
||||
ba.timer(1.0, light.delete)
|
||||
|
||||
ba.cameraflash(duration=10.0)
|
||||
self._update_scoreboard()
|
||||
|
||||
def end_game(self) -> None:
|
||||
results = ba.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 id, team in enumerate(self.teams):
|
||||
self._scoreboard.set_team_value(team, team.score, winscore)
|
||||
#self.postes(id)
|
||||
|
||||
def spawn_player(self, player: Player) -> ba.Actor:
|
||||
if bsuSpaz is None:
|
||||
spaz = self.spawn_player_spaz(player)
|
||||
else:
|
||||
ps.PlayerSpaz = bsuSpaz.BskSpaz
|
||||
spaz = self.spawn_player_spaz(player)
|
||||
ps.PlayerSpaz = bsuSpaz.OldPlayerSpaz
|
||||
|
||||
if self._speed:
|
||||
spaz.node.hockey = True
|
||||
return spaz
|
||||
|
||||
def handlemessage(self, msg: Any) -> Any:
|
||||
if isinstance(msg, ba.PlayerDiedMessage):
|
||||
super().handlemessage(msg)
|
||||
self.respawn_player(msg.getplayer(Player))
|
||||
elif isinstance(msg, BallDiedMessage):
|
||||
if not self.has_ended():
|
||||
ba.timer(3.0, self._spawn_ball)
|
||||
else:
|
||||
super().handlemessage(msg)
|
||||
|
||||
def postes(self, team_id: int):
|
||||
if not hasattr(self._map, 'poste_'+str(team_id)):
|
||||
setattr(self._map, 'poste_'+str(team_id),
|
||||
Palos(team=team_id,
|
||||
position=Points.postes['pal_' +
|
||||
str(team_id)]).autoretain())
|
||||
|
||||
def _flash_ball_spawn(self) -> None:
|
||||
light = ba.newnode('light',
|
||||
attrs={
|
||||
'position': self._ball_spawn_pos,
|
||||
'height_attenuated': False,
|
||||
'color': (1, 0, 0)
|
||||
})
|
||||
ba.animate(light, 'intensity', {0.0: 0, 0.25: 1, 0.5: 0}, loop=True)
|
||||
ba.timer(1.0, light.delete)
|
||||
|
||||
def _spawn_ball(self) -> None:
|
||||
ba.playsound(self._swipsound)
|
||||
ba.playsound(self._whistle_sound)
|
||||
self._flash_ball_spawn()
|
||||
assert self._ball_spawn_pos is not None
|
||||
self._ball = Ball(position=self._ball_spawn_pos)
|
||||
|
||||
class Aro(ba.Actor):
|
||||
def __init__(self, team: int = 0,
|
||||
position: Sequence[float] = (0.0, 1.0, 0.0)):
|
||||
super().__init__()
|
||||
act = self.getactivity()
|
||||
shared = SharedObjects.get()
|
||||
setattr(self, 'team', team)
|
||||
setattr(self, 'locs', [])
|
||||
|
||||
# Material Para; Traspasar Objetos
|
||||
self.no_collision = ba.Material()
|
||||
self.no_collision.add_actions(
|
||||
actions=(('modify_part_collision', 'collide', False)))
|
||||
|
||||
self.collision = ba.Material()
|
||||
self.collision.add_actions(
|
||||
actions=(('modify_part_collision', 'collide', True)))
|
||||
|
||||
# Score
|
||||
self._score_region_material = ba.Material()
|
||||
self._score_region_material.add_actions(
|
||||
conditions=('they_have_material', act.ball_material),
|
||||
actions=(('modify_part_collision', 'collide',
|
||||
True), ('modify_part_collision', 'physical', False),
|
||||
('call', 'at_connect', self._annotation)))
|
||||
|
||||
self._spawn_pos = (position[0], position[1], position[2])
|
||||
self._materials_region0 = [self.collision,
|
||||
shared.footing_material]
|
||||
|
||||
model = None
|
||||
tex = ba.gettexture('null')
|
||||
|
||||
pmats = [self.no_collision]
|
||||
self.node = ba.newnode('prop',
|
||||
delegate=self,
|
||||
attrs={
|
||||
'model': model,
|
||||
'color_texture': tex,
|
||||
'body': 'box',
|
||||
'reflection': 'soft',
|
||||
'reflection_scale': [1.5],
|
||||
'shadow_size': 0.1,
|
||||
'position': self._spawn_pos,
|
||||
'materials': pmats})
|
||||
|
||||
self.scale = scale = 1.4
|
||||
ba.animate(self.node, 'model_scale', {0: 0})
|
||||
|
||||
pos = (position[0], position[1]+0.6, position[2])
|
||||
self.regions: List[ba.Node] = [
|
||||
ba.newnode('region',
|
||||
attrs={'position': position,
|
||||
'scale': (0.6, 0.05, 0.6),
|
||||
'type': 'box',
|
||||
'materials': self._materials_region0}),
|
||||
|
||||
ba.newnode('region',
|
||||
attrs={'position': pos,
|
||||
'scale': (0.5, 0.3, 0.9),
|
||||
'type': 'box',
|
||||
'materials': [self._score_region_material]})
|
||||
]
|
||||
self.regions[0].connectattr('position', self.node, 'position')
|
||||
#self.regions[0].connectattr('position', self.regions[1], 'position')
|
||||
|
||||
locs_count = 9
|
||||
pos = list(position)
|
||||
|
||||
try:
|
||||
id = 0 if team == 1 else 1
|
||||
color = act.teams[id].color
|
||||
except: color = (1,1,1)
|
||||
|
||||
while locs_count > 1:
|
||||
scale = (1.5 * 0.1 * locs_count) + 0.8
|
||||
|
||||
self.locs.append(ba.newnode('locator',
|
||||
owner=self.node,
|
||||
attrs={'shape': 'circleOutline',
|
||||
'position': pos,
|
||||
'color': color,
|
||||
'opacity': 1.0,
|
||||
'size': [scale],
|
||||
'draw_beauty': True,
|
||||
'additive': False}))
|
||||
|
||||
pos[1] -= 0.1
|
||||
locs_count -= 1
|
||||
|
||||
def _annotation(self):
|
||||
assert len(self.regions) >= 2
|
||||
ball = self.getactivity()._ball
|
||||
|
||||
if ball:
|
||||
p = self.regions[0].position
|
||||
ball.node.position = p
|
||||
ball.node.velocity = (0.0, 0.0, 0.0)
|
||||
|
||||
act = self.getactivity()
|
||||
act._handle_score(self.team)
|
||||
|
||||
def handlemessage(self, msg: Any) -> Any:
|
||||
if isinstance(msg, ba.DieMessage):
|
||||
if self.node.exists():
|
||||
self.node.delete()
|
||||
else:
|
||||
super().handlemessage(msg)
|
||||
|
||||
class Cuadro(ba.Actor):
|
||||
def __init__(self, team: int = 0,
|
||||
position: Sequence[float] = (0.0, 1.0, 0.0)):
|
||||
super().__init__()
|
||||
act = self.getactivity()
|
||||
shared = SharedObjects.get()
|
||||
setattr(self, 'locs', [])
|
||||
|
||||
self.collision = ba.Material()
|
||||
self.collision.add_actions(
|
||||
actions=(('modify_part_collision', 'collide', True)))
|
||||
|
||||
pos = (position[0], position[1]+0.9, position[2]+1.5)
|
||||
self.region: ba.Node = ba.newnode('region',
|
||||
attrs={'position': pos,
|
||||
'scale': (0.5, 2.7, 2.5),
|
||||
'type': 'box',
|
||||
'materials': [self.collision,
|
||||
shared.footing_material]})
|
||||
|
||||
#self.shield = ba.newnode('shield', attrs={'radius': 1.0, 'color': (0,10,0)})
|
||||
#self.region.connectattr('position', self.shield, 'position')
|
||||
|
||||
position = (position[0], position[1], position[2]+0.09)
|
||||
pos = list(position)
|
||||
oldpos = list(position)
|
||||
old_count = 14
|
||||
|
||||
count = old_count
|
||||
count_y = 9
|
||||
|
||||
try:
|
||||
id = 0 if team == 1 else 1
|
||||
color = act.teams[id].color
|
||||
except: color = (1,1,1)
|
||||
|
||||
while(count_y != 1):
|
||||
|
||||
while(count != 1):
|
||||
pos[2] += 0.19
|
||||
|
||||
self.locs.append(
|
||||
ba.newnode('locator',
|
||||
owner=self.region,
|
||||
attrs={'shape': 'circle',
|
||||
'position': pos,
|
||||
'size': [0.5],
|
||||
'color': color,
|
||||
'opacity': 1.0,
|
||||
'draw_beauty': True,
|
||||
'additive': False}))
|
||||
count -= 1
|
||||
|
||||
|
||||
count = old_count
|
||||
pos[1] += 0.2
|
||||
pos[2] = oldpos[2]
|
||||
count_y -= 1
|
||||
|
||||
def handlemessage(self, msg: Any) -> Any:
|
||||
if isinstance(msg, ba.DieMessage):
|
||||
if self.node.exists():
|
||||
self.node.delete()
|
||||
else:
|
||||
super().handlemessage(msg)
|
||||
|
||||
class Palos(ba.Actor):
|
||||
def __init__(self, team: int = 0,
|
||||
position: Sequence[float] = (0.0, 1.0, 0.0)):
|
||||
super().__init__()
|
||||
shared = SharedObjects.get()
|
||||
activity = self.getactivity()
|
||||
self._pos = position
|
||||
self.aro = None
|
||||
self.cua = None
|
||||
|
||||
# Material Para; Traspasar Objetos
|
||||
self.no_collision = ba.Material()
|
||||
self.no_collision.add_actions(
|
||||
actions=(('modify_part_collision', 'collide', False)))
|
||||
|
||||
#
|
||||
self.collision = ba.Material()
|
||||
self.collision.add_actions(
|
||||
actions=(('modify_part_collision', 'collide', True)))
|
||||
|
||||
# Spawn just above the provided point.
|
||||
self._spawn_pos = (position[0], position[2]+2.5, position[2])
|
||||
|
||||
model = ba.getmodel('flagPole')
|
||||
tex = ba.gettexture('flagPoleColor')
|
||||
|
||||
pmats = [self.no_collision]
|
||||
self.node = ba.newnode('prop',
|
||||
delegate=self,
|
||||
attrs={
|
||||
'model': model,
|
||||
'color_texture': tex,
|
||||
'body': 'puck',
|
||||
'reflection': 'soft',
|
||||
'reflection_scale': [2.6],
|
||||
'shadow_size': 0,
|
||||
'is_area_of_interest': True,
|
||||
'position': self._spawn_pos,
|
||||
'materials': pmats
|
||||
})
|
||||
self.scale = scale = 4.0
|
||||
ba.animate(self.node, 'model_scale', {0: scale})
|
||||
|
||||
self.loc = ba.newnode('locator',
|
||||
owner=self.node,
|
||||
attrs={'shape': 'circle',
|
||||
'position': position,
|
||||
'color': (1,1,0),
|
||||
'opacity': 1.0,
|
||||
'draw_beauty': False,
|
||||
'additive': True})
|
||||
|
||||
self._y = _y = 0.30
|
||||
_x = -0.25 if team == 1 else 0.25
|
||||
_pos = (position[0]+_x, position[1]-1.5 + _y, position[2])
|
||||
self.region = ba.newnode('region',
|
||||
attrs={
|
||||
'position': _pos,
|
||||
'scale': (0.4, 8, 0.4),
|
||||
'type': 'box',
|
||||
'materials': [self.collision]})
|
||||
self.region.connectattr('position', self.node, 'position')
|
||||
|
||||
_y = self._y
|
||||
position = self._pos
|
||||
if team == 0:
|
||||
pos = (position[0]-0.8, position[1] + 2.0 + _y, position[2])
|
||||
else: pos = (position[0]+0.8, position[1] + 2.0 + _y, position[2])
|
||||
|
||||
if self.aro is None:
|
||||
self.aro = Aro(team, pos).autoretain()
|
||||
|
||||
if self.cua is None:
|
||||
pos = (position[0], position[1] + 1.8 + _y, position[2]-1.4)
|
||||
self.cua = Cuadro(team, pos).autoretain()
|
||||
|
||||
def handlemessage(self, msg: Any) -> Any:
|
||||
if isinstance(msg, ba.DieMessage):
|
||||
if self.node.exists():
|
||||
self.node.delete()
|
||||
else:
|
||||
super().handlemessage(msg)
|
||||
322
dist/ba_root/mods/games/crazyBoxes.py
vendored
Normal file
322
dist/ba_root/mods/games/crazyBoxes.py
vendored
Normal file
|
|
@ -0,0 +1,322 @@
|
|||
# ba_meta require api 6
|
||||
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, TypeVar
|
||||
|
||||
import ba, random, _ba
|
||||
from math import cos, sin
|
||||
from bastd.actor.bomb import Bomb, BombFactory, Blast, ExplodeMessage
|
||||
from bastd.actor.playerspaz import PlayerSpaz
|
||||
from bastd.actor.scoreboard import Scoreboard
|
||||
from bastd.gameutils import SharedObjects
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Type, List, Dict, Tuple, Union, Sequence, Optional, Callable
|
||||
|
||||
class DisconnectMessage():
|
||||
pass
|
||||
class ConnectMessage():
|
||||
pass
|
||||
|
||||
class Box(ba.Actor):
|
||||
# should create our own node instead
|
||||
def __init__(self,
|
||||
velocity: Sequence[float] = (0.0, 0.0, 0.0),
|
||||
bomb_type: str = 'normal',
|
||||
box_type: str = 'small',
|
||||
bomb_scale: float = 1.0):
|
||||
super().__init__()
|
||||
shared = SharedObjects.get()
|
||||
factory = BombFactory.get()
|
||||
self.pos: Sequence[float] = ((-11.857367) + round(random.uniform(0, 23), 6),
|
||||
round(random.uniform(2, 9), 2),
|
||||
(-4.3599663) + round(random.uniform(0, 8), 6))
|
||||
self.random = self.force = self.ang = self.x = self.z = self.momentum = 0
|
||||
|
||||
self.typee = box_type
|
||||
self._exploded, self.ground = False, False
|
||||
self._explode_callbacks: List[Callable[[Bomb, Blast], Any]] = []
|
||||
|
||||
materials: Tuple[ba.Material, ...]
|
||||
materials = (factory.bomb_material, shared.footing_material,
|
||||
shared.object_material)
|
||||
|
||||
if box_type == 'small':
|
||||
self.data = {
|
||||
'walk_force': 9.35,
|
||||
'jump_force': 190,
|
||||
'walk_cd': 1474,
|
||||
'jump_cd': 1500,
|
||||
'light_color': (1, 0, 0.4),
|
||||
'points': 100,
|
||||
'texture': ba.gettexture('star'),
|
||||
'size': 0.9}
|
||||
elif box_type == 'large':
|
||||
self.data = {
|
||||
'walk_force': 13.3905,
|
||||
'jump_force': 260,
|
||||
'walk_cd': 900,
|
||||
'jump_cd': 3000,
|
||||
'light_color': (0, 0.2, 1.55),
|
||||
'points': 50,
|
||||
'texture': ba.gettexture('egg2'),
|
||||
'size': 1.2}
|
||||
|
||||
self.node = ba.newnode('prop',
|
||||
delegate=self,
|
||||
attrs={
|
||||
'position': self.pos,
|
||||
'velocity': velocity,
|
||||
'model': ba.getmodel('powerup'),
|
||||
'light_model': ba.getmodel('powerup'),
|
||||
'body': 'crate',
|
||||
'model_scale': self.data.get('size'),
|
||||
'body_scale': self.data.get('size'),
|
||||
'density':0.5,
|
||||
'gravity_scale': 0.5,
|
||||
'shadow_size': 0.5,
|
||||
'color_texture': self.data.get('texture'),
|
||||
'reflection': 'soft',
|
||||
'reflection_scale': [0.23],
|
||||
'materials': materials})
|
||||
self.light = ba.newnode('light',
|
||||
attrs={
|
||||
'color': self.data.get('light_color'),
|
||||
'radius': 0.4
|
||||
})
|
||||
self.node.connectattr('position',self.light,'position')
|
||||
self.move_used = self.highjump_used = self.jump_used = False
|
||||
ba.animate(self.node, 'model_scale', {0.0:0.0, 0.7:self.data.get('size')})
|
||||
ba.timer(1000*0.001, self.start_updating)
|
||||
|
||||
def start_updating(self):
|
||||
self.move_timer = ba.Timer(100*0.001, ba.WeakCall(self.update_ai), repeat=True)
|
||||
def refresh(self, type_: str = 'move'):
|
||||
if type_ == 'move':
|
||||
self.move_used = False
|
||||
elif type_ == 'jump':
|
||||
self.jump_used = False
|
||||
elif type_ == 'highjump':
|
||||
self.highjump_used = False
|
||||
|
||||
|
||||
def move(self):
|
||||
try:
|
||||
if self.node.exists() and not self.move_used and self.node.position[1] < 1.0:
|
||||
self.move_used = True
|
||||
ba.timer(self.data.get('walk_cd')*0.001, lambda: self.refresh('move'))
|
||||
self.ang = random.randint(0,360)
|
||||
self.x = cos(self.ang) * self.data.get('walk_force')
|
||||
self.z = sin(self.ang) * self.data.get('walk_force')
|
||||
self.node.velocity = (self.x, 0, self.z)
|
||||
except: pass
|
||||
def high_jump(self):
|
||||
try:
|
||||
if self.node.exists() and not self.highjump_used:
|
||||
self.highjump_used = True
|
||||
ba.timer(10000*0.001, lambda: self.refresh('highjump'))
|
||||
self.node.handlemessage("impulse", self.node.position[0], self.node.position[1], self.node.position[2],
|
||||
0.0, 0.0, 0.0,
|
||||
self.data.get('jump_force')+70,0,0,0,0,1,0)
|
||||
except: pass
|
||||
def jump(self):
|
||||
try:
|
||||
if self.node.exists() and not self.jump_used:
|
||||
self.jump_used = True
|
||||
ba.timer(self.data.get('jump_cd')*0.001, lambda: self.refresh('jump'))
|
||||
self.node.handlemessage("impulse", self.node.position[0], self.node.position[1], self.node.position[2],
|
||||
0.0, 0.0, 0.0,
|
||||
self.data.get('jump_force'),0,0,0,0,1,0)
|
||||
except: pass
|
||||
def act_crazy(self):
|
||||
try:
|
||||
if self.node.exists():
|
||||
self.node.velocity = (self.node.velocity[0]+round(random.uniform(-2.0, 2.0),2), random.random()*1.5, self.node.velocity[2]+round(random.uniform(-2.0, 2.0),2))
|
||||
self.node.extra_acceleration = (self.node.velocity[0]*1.3, self.node.velocity[1]*45, self.node.velocity[2]*1.3)
|
||||
except: pass
|
||||
|
||||
def update_ai(self):
|
||||
if not self.node.exists():
|
||||
self.update_ai = None
|
||||
return
|
||||
for p in self.activity.players:
|
||||
if p.actor.node.exists():
|
||||
if p.actor.node.hold_node == self.node:
|
||||
self.act_crazy()
|
||||
else:
|
||||
self.node.extra_acceleration = (0, 0, 0)
|
||||
self.random = random.randint(1,4)
|
||||
if self.random == 1: self.move()
|
||||
elif self.random == 2: self.jump()
|
||||
elif self.random == 3 and self.typee == 'large': self.high_jump()
|
||||
|
||||
def on_expire(self) -> None:
|
||||
super().on_expire()
|
||||
self._explode_callbacks = []
|
||||
def respawn(self) -> None: pass
|
||||
|
||||
def _handle_die(self) -> None:
|
||||
# self.respawn()
|
||||
if self.node:
|
||||
self.light.delete()
|
||||
self.node.delete()
|
||||
def _handle_oob(self) -> None:
|
||||
self.handlemessage(ba.DieMessage())
|
||||
def add_explode_callback(self, call: Callable[[Bomb, Blast], Any]) -> None:
|
||||
self._explode_callbacks.append(call)
|
||||
def explode(self) -> None:
|
||||
if self._exploded:
|
||||
return
|
||||
self._exploded = True
|
||||
if self.node:
|
||||
blast = Blast(position=self.node.position,
|
||||
velocity=self.node.velocity,
|
||||
blast_radius=2.4,
|
||||
blast_type='tnt',
|
||||
hit_type='normal',
|
||||
hit_subtype='tnt').autoretain()
|
||||
for callback in self._explode_callbacks:
|
||||
callback(self, blast)
|
||||
ba.timer(0.001, ba.WeakCall(self.handlemessage, ba.DieMessage()))
|
||||
def _add_material(self, material: ba.Material) -> None:
|
||||
if not self.node:
|
||||
return
|
||||
materials = self.node.materials
|
||||
if material not in materials:
|
||||
assert isinstance(materials, tuple)
|
||||
self.node.materials = materials + (material, )
|
||||
|
||||
def _handle_hit(self, msg: ba.HitMessage) -> None:
|
||||
if msg.hit_subtype == 'tnt': return
|
||||
if not self._exploded and not msg.hit_type == 'punch':
|
||||
self.update_ai = None
|
||||
ba.timer(0.1 + random.random() * 0.1,
|
||||
ba.WeakCall(self.handlemessage, ExplodeMessage()))
|
||||
killer = msg.get_source_player(ba.Player)
|
||||
if killer is not None:
|
||||
assert killer.team is not None
|
||||
self.activity.stats.player_scored(killer, self.data.get('points'), screenmessage=False, color=(killer.actor.node.color[0]+0.3, killer.actor.node.color[1]+0.3, killer.actor.node.color[2]+0.3))
|
||||
killer.team.score += self.data.get('points')
|
||||
ba.playsound(self.activity._dingsound)
|
||||
self.activity._update_scoreboard()
|
||||
self.move_timer = None
|
||||
if msg.srcnode: pass
|
||||
def handlemessage(self, msg: Any) -> Any:
|
||||
if isinstance(msg, ExplodeMessage):
|
||||
self.explode()
|
||||
elif isinstance(msg, ba.HitMessage):
|
||||
self._handle_hit(msg)
|
||||
elif isinstance(msg, ba.DieMessage):
|
||||
ba.timer(random.randrange(1500,5020,50)*0.001, lambda: Box(box_type=self.typee).autoretain())
|
||||
self._handle_die()
|
||||
elif isinstance(msg, ba.OutOfBoundsMessage):
|
||||
self._handle_oob()
|
||||
else:
|
||||
super().handlemessage(msg)
|
||||
|
||||
|
||||
class Player(ba.Player['Team']):
|
||||
...
|
||||
class Team(ba.Team[Player]):
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.score = 0
|
||||
|
||||
|
||||
# ba_meta export game
|
||||
class CrazyBoxGame(ba.TeamGameActivity[Player, Team]):
|
||||
"""A game type based on acquiring kills."""
|
||||
|
||||
name = 'Crazy Box'
|
||||
description = 'Blow up the Crazy Boxes!'
|
||||
announce_player_deaths = True
|
||||
|
||||
@classmethod
|
||||
def get_available_settings(
|
||||
cls, sessiontype: Type[ba.Session]) -> List[ba.Setting]:
|
||||
settings = [
|
||||
ba.IntSetting('Points to win per Player',min_value=50,default=800, increment=50),
|
||||
ba.IntSetting('Small Box Count',min_value=1,default=1, increment=1),
|
||||
ba.IntSetting('Large Box Count',min_value=1,default=2, increment=1),
|
||||
ba.IntChoiceSetting('Time Limit', choices=[('None', 0),('1 Minute', 60),('2 Minutes', 120),('5 Minutes', 300),('10 Minutes', 600),('20 Minutes', 1200)],default=0),
|
||||
ba.FloatChoiceSetting('Respawn Times',choices=[('Shorter', 0.25),('Short', 0.5),('Normal', 1.0),('Long', 2.0),('Longer', 4.0)], default=1.0),
|
||||
ba.BoolSetting('Epic Mode', default=False)
|
||||
]
|
||||
return settings
|
||||
|
||||
@classmethod
|
||||
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
|
||||
return (issubclass(sessiontype, ba.DualTeamSession)
|
||||
or issubclass(sessiontype, ba.FreeForAllSession))
|
||||
|
||||
@classmethod
|
||||
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
|
||||
return ['Football Stadium']
|
||||
|
||||
def __init__(self, settings: dict):
|
||||
super().__init__(settings)
|
||||
self.co = int(settings["Small Box Count"])
|
||||
self.c2 = int(settings["Large Box Count"])
|
||||
self._scoreboard = Scoreboard()
|
||||
self._score_to_win: Optional[int] = None
|
||||
self._dingsound = ba.getsound('dingSmall')
|
||||
self._epic_mode = bool(settings['Epic Mode'])
|
||||
self.boxes_to_win = int(settings['Points to win per Player'])
|
||||
self._time_limit = float(settings['Time Limit'])
|
||||
self.region: List[ba.NodeActor] = []
|
||||
self.block_box_mat = ba.Material()
|
||||
self.block_box_mat.add_actions(conditions=('they_have_material', BombFactory.get().bomb_material),
|
||||
actions=(('modify_part_collision', 'collide', True),
|
||||
('modify_part_collision', 'physical', True)))
|
||||
|
||||
self.slow_motion = self._epic_mode
|
||||
self.default_music = (ba.MusicType.EPIC if self._epic_mode else
|
||||
ba.MusicType.FORWARD_MARCH)
|
||||
|
||||
def _setup_standard_tnt_drops(self) -> None:
|
||||
pass
|
||||
|
||||
def get_instance_description(self) -> Union[str, Sequence]:
|
||||
return 'Blow up boxes and score ${ARG1} points to win!', self.boxes_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.setup_standard_time_limit(self._time_limit)
|
||||
for i in range(self.co):
|
||||
Box().autoretain()
|
||||
for a in range(self.c2):
|
||||
Box(box_type='large').autoretain()
|
||||
self.setup_standard_powerup_drops()
|
||||
b = self.map.defs.boxes['map_bounds']
|
||||
self.region.append(ba.NodeActor(ba.newnode('region', attrs={'position':(b[0], b[1]+10, b[2]), 'type':'box', 'scale': (b[6], 1.0, b[8]), 'materials': [self.block_box_mat]})))
|
||||
|
||||
self._score_to_win = (self.boxes_to_win *
|
||||
max(1, max(len(t.players) for t in self.teams)))
|
||||
self._update_scoreboard()
|
||||
|
||||
def handlemessage(self, msg: Any) -> Any:
|
||||
if isinstance(msg, ba.PlayerDiedMessage):
|
||||
super().handlemessage(msg)
|
||||
player = msg.getplayer(Player)
|
||||
self.respawn_player(player)
|
||||
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)
|
||||
if team.score >= self._score_to_win: ba.timer(500*0.001, self.end_game)
|
||||
|
||||
def end_game(self) -> None:
|
||||
results = ba.GameResults()
|
||||
for team in self.teams:
|
||||
results.set_team_score(team, team.score)
|
||||
self.end(results=results)
|
||||
361
dist/ba_root/mods/games/game.py
vendored
Normal file
361
dist/ba_root/mods/games/game.py
vendored
Normal file
|
|
@ -0,0 +1,361 @@
|
|||
"""Quake Game Activity"""
|
||||
# ba_meta require api 6
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import random
|
||||
import enum
|
||||
import ba
|
||||
|
||||
from bastd.actor.scoreboard import Scoreboard
|
||||
from bastd.actor.powerupbox import PowerupBox
|
||||
from bastd.gameutils import SharedObjects
|
||||
|
||||
import quake.rocket
|
||||
import quake.railgun
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional, List, Any, Type, Union, Sequence
|
||||
|
||||
|
||||
class Player(ba.Player['Team']):
|
||||
"""Our player"""
|
||||
|
||||
|
||||
class Team(ba.Team[Player]):
|
||||
"""Our team"""
|
||||
def __init__(self) -> None:
|
||||
self.score = 0
|
||||
|
||||
|
||||
class WeaponType(enum.Enum):
|
||||
"""Type of weapon"""
|
||||
ROCKET = 0
|
||||
RAILGUN = 1
|
||||
|
||||
|
||||
class ObstaclesForm(enum.Enum):
|
||||
"""Obstacle form"""
|
||||
CUBE = 0
|
||||
SPHERE = 1
|
||||
RANDOM = 2
|
||||
|
||||
|
||||
# ba_meta export game
|
||||
class QuakeGame(ba.TeamGameActivity[Player, Team]):
|
||||
"""Quake Team Game Activity"""
|
||||
name = 'Quake'
|
||||
description = 'Kill a set number of enemies to win.'
|
||||
available_settings = [
|
||||
ba.IntSetting(
|
||||
'Kills to Win Per Player',
|
||||
default=15,
|
||||
min_value=1,
|
||||
increment=1,
|
||||
),
|
||||
ba.IntChoiceSetting(
|
||||
'Time Limit',
|
||||
choices=[('None', 0), ('1 Minute', 60), ('2 Minutes', 120),
|
||||
('5 Minutes', 300), ('10 Minutes', 600),
|
||||
('20 Minutes', 1200)],
|
||||
default=0,
|
||||
),
|
||||
ba.FloatChoiceSetting(
|
||||
'Respawn Times',
|
||||
choices=[('At once', 0.0), ('Shorter', 0.25), ('Short', 0.5),
|
||||
('Normal', 1.0), ('Long', 2.0), ('Longer', 4.0)],
|
||||
default=1.0,
|
||||
),
|
||||
ba.BoolSetting(
|
||||
'Speed',
|
||||
default=True,
|
||||
),
|
||||
ba.BoolSetting(
|
||||
'Enable Jump',
|
||||
default=True,
|
||||
),
|
||||
ba.BoolSetting(
|
||||
'Enable Pickup',
|
||||
default=True,
|
||||
),
|
||||
ba.BoolSetting(
|
||||
'Enable Bomb',
|
||||
default=False,
|
||||
),
|
||||
ba.BoolSetting(
|
||||
'Obstacles',
|
||||
default=True,
|
||||
),
|
||||
ba.IntChoiceSetting(
|
||||
'Obstacles Form',
|
||||
choices=[('Cube', ObstaclesForm.CUBE.value),
|
||||
('Sphere', ObstaclesForm.SPHERE.value),
|
||||
('Random', ObstaclesForm.RANDOM.value)],
|
||||
default=0,
|
||||
),
|
||||
ba.IntChoiceSetting(
|
||||
'Weapon Type',
|
||||
choices=[('Rocket', WeaponType.ROCKET.value),
|
||||
('Railgun', WeaponType.RAILGUN.value)],
|
||||
default=WeaponType.ROCKET.value,
|
||||
),
|
||||
ba.BoolSetting(
|
||||
'Obstacles Mirror Shots',
|
||||
default=False,
|
||||
),
|
||||
ba.IntSetting(
|
||||
'Obstacles Count',
|
||||
default=16,
|
||||
min_value=0,
|
||||
increment=2,
|
||||
),
|
||||
ba.BoolSetting(
|
||||
'Random Obstacles Color',
|
||||
default=True,
|
||||
),
|
||||
ba.BoolSetting(
|
||||
'Epic Mode',
|
||||
default=False,
|
||||
),
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def supports_session_type(cls, sessiontype: Type[ba.Session]) -> bool:
|
||||
return issubclass(sessiontype, ba.MultiTeamSession) or issubclass(
|
||||
sessiontype, ba.FreeForAllSession)
|
||||
|
||||
@classmethod
|
||||
def get_supported_maps(cls, sessiontype: Type[ba.Session]) -> List[str]:
|
||||
# TODO add more maps
|
||||
return ['Football Stadium', 'Monkey Face', 'Doom Shroom']
|
||||
|
||||
def __init__(self, settings) -> None:
|
||||
super().__init__(settings)
|
||||
self._epic_mode = self.settings_raw['Epic Mode']
|
||||
self._score_to_win = self.settings_raw['Kills to Win Per Player']
|
||||
self._time_limit = self.settings_raw['Time Limit']
|
||||
self._obstacles_enabled = self.settings_raw['Obstacles']
|
||||
self._obstacles_count = self.settings_raw['Obstacles Count']
|
||||
self._speed_enabled = self.settings_raw['Speed']
|
||||
self._bomb_enabled = self.settings_raw['Enable Bomb']
|
||||
self._pickup_enabled = self.settings_raw['Enable Pickup']
|
||||
self._jump_enabled = self.settings_raw['Enable Jump']
|
||||
self._weapon_type = WeaponType(self.settings_raw['Weapon Type'])
|
||||
self.default_music = (ba.MusicType.EPIC
|
||||
if self._epic_mode else ba.MusicType.GRAND_ROMP)
|
||||
self.slow_motion = self._epic_mode
|
||||
|
||||
self.announce_player_deaths = True
|
||||
self._scoreboard = Scoreboard()
|
||||
self._ding_sound = ba.getsound('dingSmall')
|
||||
|
||||
self._shield_dropper: Optional[ba.Timer] = None
|
||||
|
||||
def get_instance_description(self) -> Union[str, Sequence]:
|
||||
return 'Kill ${ARG1} enemies.', self._score_to_win
|
||||
|
||||
def on_team_join(self, team: Team) -> None:
|
||||
team.score = 0
|
||||
if self.has_begun():
|
||||
self._update_scoreboard()
|
||||
|
||||
def on_begin(self) -> None:
|
||||
ba.TeamGameActivity.on_begin(self)
|
||||
ba.getactivity().globalsnode.tint = (0.5, 0.7, 1)
|
||||
self.drop_shield()
|
||||
self._shield_dropper = ba.Timer(8,
|
||||
ba.WeakCall(self.drop_shield),
|
||||
repeat=True)
|
||||
self.setup_standard_time_limit(self._time_limit)
|
||||
if self._obstacles_enabled:
|
||||
count = self._obstacles_count
|
||||
gamemap = self.map.getname()
|
||||
for i in range(count): # TODO: tidy up around here
|
||||
if gamemap == '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,
|
||||
mirror=self.settings_raw['Obstacles Mirror Shots'],
|
||||
form=self.settings_raw['Obstacles Form']).autoretain()
|
||||
|
||||
self._update_scoreboard()
|
||||
|
||||
def drop_shield(self) -> None:
|
||||
"""Drop a shield powerup in random place"""
|
||||
# FIXME: should use map defs
|
||||
shield = PowerupBox(poweruptype='shield',
|
||||
position=(random.uniform(-10, 10), 6,
|
||||
random.uniform(-5, 5))).autoretain()
|
||||
|
||||
ba.playsound(self._ding_sound)
|
||||
|
||||
p_light = ba.newnode('light',
|
||||
owner=shield.node,
|
||||
attrs={
|
||||
'position': (0, 0, 0),
|
||||
'color': (0.3, 0.0, 0.4),
|
||||
'radius': 0.3,
|
||||
'intensity': 2,
|
||||
'volume_intensity_scale': 10.0
|
||||
})
|
||||
|
||||
shield.node.connectattr('position', p_light, 'position')
|
||||
|
||||
ba.animate(p_light, 'intensity', {0: 2, 8: 0})
|
||||
|
||||
def spawn_player(self, player: Player) -> None:
|
||||
spaz = self.spawn_player_spaz(player)
|
||||
if self._weapon_type == WeaponType.ROCKET:
|
||||
quake.rocket.RocketLauncher().give(spaz)
|
||||
elif self._weapon_type == WeaponType.RAILGUN:
|
||||
quake.railgun.Railgun().give(spaz)
|
||||
spaz.connect_controls_to_player(enable_jump=self._jump_enabled,
|
||||
enable_pickup=self._pickup_enabled,
|
||||
enable_bomb=self._bomb_enabled,
|
||||
enable_fly=False)
|
||||
|
||||
spaz.node.hockey = self._speed_enabled
|
||||
spaz.spaz_light = ba.newnode('light',
|
||||
owner=spaz.node,
|
||||
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, ba.PlayerDiedMessage):
|
||||
ba.TeamGameActivity.handlemessage(self, msg)
|
||||
player = msg.getplayer(Player)
|
||||
self.respawn_player(player)
|
||||
killer = msg.getkillerplayer(Player)
|
||||
if killer is None:
|
||||
return
|
||||
|
||||
# handle team-kills
|
||||
if killer.team is player.team:
|
||||
# in free-for-all, killing yourself loses you a point
|
||||
if isinstance(self.session, ba.FreeForAllSession):
|
||||
new_score = player.team.score - 1
|
||||
new_score = max(0, new_score)
|
||||
player.team.score = new_score
|
||||
# in teams-mode it gives a point to the other team
|
||||
else:
|
||||
ba.playsound(self._ding_sound)
|
||||
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
|
||||
ba.playsound(self._ding_sound)
|
||||
# in FFA show our score since its hard to find on
|
||||
# the scoreboard
|
||||
assert killer.actor is not None
|
||||
# noinspection PyUnresolvedReferences
|
||||
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)
|
||||
if any(team.score >= self._score_to_win for team in self.teams):
|
||||
ba.timer(0.5, self.end_game)
|
||||
|
||||
else:
|
||||
ba.TeamGameActivity.handlemessage(self, msg)
|
||||
|
||||
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 = ba.GameResults()
|
||||
for team in self.teams:
|
||||
results.set_team_score(team, team.score)
|
||||
|
||||
self.end(results=results)
|
||||
|
||||
|
||||
class Obstacle(ba.Actor):
|
||||
"""Scene object"""
|
||||
|
||||
def __init__(self,
|
||||
position,
|
||||
form=ObstaclesForm.CUBE,
|
||||
mirror=False) -> None:
|
||||
ba.Actor.__init__(self)
|
||||
|
||||
if form == ObstaclesForm.CUBE:
|
||||
model = 'tnt'
|
||||
body = 'crate'
|
||||
elif form == ObstaclesForm.SPHERE:
|
||||
model = 'bomb'
|
||||
body = 'sphere'
|
||||
else: # ObstaclesForm.RANDOM:
|
||||
model = random.choice(['tnt', 'bomb'])
|
||||
body = 'sphere' if model == 'bomb' else 'crate'
|
||||
|
||||
self.node = ba.newnode(
|
||||
'prop',
|
||||
delegate=self,
|
||||
attrs={
|
||||
'position':
|
||||
position,
|
||||
'model':
|
||||
ba.getmodel(model),
|
||||
'body':
|
||||
body,
|
||||
'body_scale':
|
||||
1.3,
|
||||
'model_scale':
|
||||
1.3,
|
||||
'reflection':
|
||||
'powerup',
|
||||
'reflection_scale': [0.7],
|
||||
'color_texture':
|
||||
ba.gettexture('bunnyColor'),
|
||||
'materials': [SharedObjects.get().footing_material]
|
||||
if mirror else [
|
||||
SharedObjects.get().object_material,
|
||||
SharedObjects.get().footing_material
|
||||
]
|
||||
})
|
||||
|
||||
def handlemessage(self, msg: Any) -> Any:
|
||||
if isinstance(msg, ba.DieMessage):
|
||||
if self.node:
|
||||
self.node.delete()
|
||||
|
||||
elif isinstance(msg, ba.OutOfBoundsMessage):
|
||||
if self.node:
|
||||
self.handlemessage(ba.DieMessage())
|
||||
|
||||
elif isinstance(msg, ba.HitMessage):
|
||||
self.node.handlemessage('impulse', msg.pos[0], msg.pos[1],
|
||||
msg.pos[2], msg.velocity[0],
|
||||
msg.velocity[1], msg.velocity[2],
|
||||
msg.magnitude, msg.velocity_magnitude,
|
||||
msg.radius, 0, msg.velocity[0],
|
||||
msg.velocity[1], msg.velocity[2])
|
||||
117
dist/ba_root/mods/games/ms_BombWar.py
vendored
Normal file
117
dist/ba_root/mods/games/ms_BombWar.py
vendored
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
# ba_meta require api 6
|
||||
|
||||
"""
|
||||
BombWar Mini game
|
||||
|
||||
by : Mr.Smoothy
|
||||
discord : mr.smoothy#5824
|
||||
download more , contribute : https://discord.gg/ucyaesh
|
||||
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
import ba
|
||||
from bastd.game.deathmatch import DeathMatchGame, Player, Team
|
||||
from bastd.actor.bomb import Bomb
|
||||
import bastd
|
||||
if TYPE_CHECKING:
|
||||
from typing import Sequence
|
||||
|
||||
from bastd.gameutils import SharedObjects
|
||||
# ba_meta export game
|
||||
class BombWar(DeathMatchGame):
|
||||
name = 'Bomb War'
|
||||
|
||||
def __init__(self, settings: dict):
|
||||
super().__init__(settings)
|
||||
|
||||
|
||||
shared = SharedObjects.get()
|
||||
self._wall_material=ba.Material()
|
||||
self._fake_wall_material=ba.Material()
|
||||
self._wall_material.add_actions(
|
||||
|
||||
actions=(
|
||||
('modify_part_collision', 'friction', 100000),
|
||||
))
|
||||
self._wall_material.add_actions(
|
||||
conditions=('they_have_material', shared.pickup_material),
|
||||
actions=(
|
||||
('modify_part_collision', 'collide', False),
|
||||
))
|
||||
|
||||
self._wall_material.add_actions(
|
||||
conditions=(('we_are_younger_than', 100),
|
||||
'and',
|
||||
('they_have_material',shared.object_material)),
|
||||
actions=(
|
||||
('modify_part_collision', 'collide', False),
|
||||
))
|
||||
self._wall_material.add_actions(
|
||||
conditions=('they_have_material',shared.footing_material),
|
||||
actions=(
|
||||
('modify_part_collision', 'friction', 9999.5),
|
||||
))
|
||||
self._wall_material.add_actions(
|
||||
conditions=('they_have_material', bastd.actor.bomb.BombFactory.get().blast_material),
|
||||
actions=(
|
||||
('modify_part_collision', 'collide', False),
|
||||
('modify_part_collision', 'physical', False)
|
||||
|
||||
))
|
||||
self._fake_wall_material.add_actions(
|
||||
conditions=('they_have_material', shared.player_material),
|
||||
actions=(
|
||||
('modify_part_collision', 'collide', True),
|
||||
('modify_part_collision', 'physical', True)
|
||||
|
||||
))
|
||||
self.blocks=[]
|
||||
|
||||
def on_begin(self) -> None:
|
||||
super().on_begin()
|
||||
self.setup_standard_time_limit(self._time_limit)
|
||||
factory = bastd.actor.bomb.BombFactory.get()
|
||||
|
||||
shared = SharedObjects.get()
|
||||
for i in [-5.5,-4.5,-3.5,-2.5,-1.5,-0.5,0.5,1.5,2.5]:
|
||||
|
||||
self.blocks.append(ba.newnode(
|
||||
'prop',
|
||||
delegate=self,
|
||||
attrs={
|
||||
'body': 'puck',
|
||||
'position': (-0.1,3,i),
|
||||
'model': ba.getmodel('tnt'),
|
||||
# 'light_model': factory.tnt_model,
|
||||
'shadow_size': 0.5,
|
||||
'gravity_scale':7.5,
|
||||
'color_texture': ba.gettexture('puckColor'),
|
||||
'reflection': 'soft',
|
||||
'reflection_scale': [1.0],
|
||||
'materials': (shared.object_material,self._wall_material,)
|
||||
}) )
|
||||
for i in [-5.5,-4.5,-3.5,-2.5,-1.5,-0.5,0.5,1.5,2.3]:
|
||||
|
||||
self.blocks.append(ba.newnode(
|
||||
'prop',
|
||||
delegate=self,
|
||||
attrs={
|
||||
'body': 'puck',
|
||||
'position': (-0.1,5,i),
|
||||
'model': ba.getmodel('tnt'),
|
||||
# 'light_model': factory.tnt_model,
|
||||
'shadow_size': 0.5,
|
||||
'gravity_scale':7.5,
|
||||
'color_texture': ba.gettexture('puckColor'),
|
||||
'reflection': 'soft',
|
||||
'reflection_scale': [1.0],
|
||||
'materials': (shared.object_material,self._wall_material,)
|
||||
}) )
|
||||
self.blocks.append(ba.NodeActor(ba.newnode('region',attrs={'position': (0,3,-6),'scale': (2,5,20),'type': 'box','materials': (self._fake_wall_material, )})))
|
||||
|
||||
# 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()
|
||||
BIN
dist/ba_root/mods/games/soccer.so
vendored
Normal file
BIN
dist/ba_root/mods/games/soccer.so
vendored
Normal file
Binary file not shown.
88
dist/ba_root/mods/maps/BasketBallMap.py
vendored
Normal file
88
dist/ba_root/mods/maps/BasketBallMap.py
vendored
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
import ba
|
||||
from bastd.gameutils import SharedObjects
|
||||
from bastd.actor import playerspaz as ps
|
||||
from bastd import maps
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Sequence, Dict, Type, List, Optional, Union
|
||||
|
||||
class BasketMap(maps.FootballStadium):
|
||||
name = 'BasketBall Stadium'
|
||||
|
||||
@classmethod
|
||||
def get_play_types(cls) -> List[str]:
|
||||
"""Return valid play types for this map."""
|
||||
return []
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
gnode = ba.getactivity().globalsnode
|
||||
gnode.tint = [(0.806, 0.8, 1.0476), (1.3, 1.2, 1.0)][0]
|
||||
gnode.ambient_color = (1.3, 1.2, 1.0)
|
||||
gnode.vignette_outer = (0.57, 0.57, 0.57)
|
||||
gnode.vignette_inner = (0.9, 0.9, 0.9)
|
||||
gnode.vr_camera_offset = (0, -0.8, -1.1)
|
||||
gnode.vr_near_clip = 0.5
|
||||
|
||||
class BasketMapV2(maps.HockeyStadium):
|
||||
name = 'BasketBall Stadium V2'
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
shared = SharedObjects.get()
|
||||
self.node.materials = [shared.footing_material]
|
||||
self.node.collide_model = ba.getcollidemodel('footballStadiumCollide')
|
||||
self.node.model = None
|
||||
self.stands.model = None
|
||||
self.floor.reflection = 'soft'
|
||||
self.floor.reflection_scale = [1.6]
|
||||
self.floor.color = (1.1, 0.05, 0.8)
|
||||
|
||||
self.background = ba.newnode('terrain',
|
||||
attrs={'model': ba.getmodel('thePadBG'),
|
||||
'lighting': False,
|
||||
'background': True,
|
||||
'color': (1.0, 0.2, 1.0),
|
||||
'color_texture': ba.gettexture('menuBG')})
|
||||
|
||||
gnode = ba.getactivity().globalsnode
|
||||
gnode.floor_reflection = True
|
||||
gnode.debris_friction = 0.3
|
||||
gnode.debris_kill_height = -0.3
|
||||
gnode.tint = [(1.2, 1.3, 1.33), (0.7, 0.9, 1.0)][1]
|
||||
gnode.ambient_color = (1.15, 1.25, 1.6)
|
||||
gnode.vignette_outer = (0.66, 0.67, 0.73)
|
||||
gnode.vignette_inner = (0.93, 0.93, 0.95)
|
||||
gnode.vr_camera_offset = (0, -0.8, -1.1)
|
||||
gnode.vr_near_clip = 0.5
|
||||
self.is_hockey = False
|
||||
|
||||
##################
|
||||
self.collision = ba.Material()
|
||||
self.collision.add_actions(
|
||||
actions=(('modify_part_collision', 'collide', True)))
|
||||
|
||||
self.regions: List[ba.Node] = [
|
||||
ba.newnode('region',
|
||||
attrs={'position': (12.676897048950195, 0.2997918128967285, 5.583303928375244),
|
||||
'scale': (1.01, 12, 28),
|
||||
'type': 'box',
|
||||
'materials': [self.collision]}),
|
||||
|
||||
ba.newnode('region',
|
||||
attrs={'position': (11.871315956115723, 0.29975247383117676, 5.711406707763672),
|
||||
'scale': (50, 12, 0.9),
|
||||
'type': 'box',
|
||||
'materials': [self.collision]}),
|
||||
|
||||
ba.newnode('region',
|
||||
attrs={'position': (-12.776557922363281, 0.30036890506744385, 4.96237850189209),
|
||||
'scale': (1.01, 12, 28),
|
||||
'type': 'box',
|
||||
'materials': [self.collision]}),
|
||||
]
|
||||
|
||||
ba._map.register_map(BasketMap)
|
||||
ba._map.register_map(BasketMapV2)
|
||||
BIN
dist/ba_root/mods/maps/BridgitMash.so
vendored
Normal file
BIN
dist/ba_root/mods/maps/BridgitMash.so
vendored
Normal file
Binary file not shown.
BIN
dist/ba_root/mods/maps/BridgitParallelo.so
vendored
Normal file
BIN
dist/ba_root/mods/maps/BridgitParallelo.so
vendored
Normal file
Binary file not shown.
56
dist/ba_root/mods/maps/MemoryGame.py
vendored
Normal file
56
dist/ba_root/mods/maps/MemoryGame.py
vendored
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
import ba
|
||||
from bastd.gameutils import SharedObjects
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Sequence, Optional, List, Dict, Type, Type , Union, Any, Literal
|
||||
|
||||
class MGdefs():
|
||||
points = {}
|
||||
boxes = {}
|
||||
points['flag_default'] = (0.17358, 3.75764, 1.99124)
|
||||
boxes['area_of_interest_bounds'] = (0.3544110667, 4.493562578, -2.518391331) + (0.0, 0.0, 0.0) + (16.64754831, 8.06138989, 18.5029888)
|
||||
boxes['map_bounds'] = (0.2608783669, 4.899663734, -3.543675157) + (0.0, 0.0, 0.0) + (29.23565494, 14.19991443, 29.92689344)
|
||||
|
||||
class MGmap(ba.Map):
|
||||
defs = MGdefs()
|
||||
name = 'Sky Tiles'
|
||||
|
||||
@classmethod
|
||||
def get_play_types(cls) -> List[str]:
|
||||
"""Return valid play types for this map."""
|
||||
return []
|
||||
|
||||
@classmethod
|
||||
def get_preview_texture_name(cls) -> str:
|
||||
return 'achievementOffYouGo'
|
||||
|
||||
@classmethod
|
||||
def on_preload(cls) -> Any:
|
||||
data: Dict[str, Any] = {
|
||||
'bgtex': ba.gettexture('menuBG'),
|
||||
'bgmodel': ba.getmodel('thePadBG')
|
||||
}
|
||||
return data
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
shared = SharedObjects.get()
|
||||
self.node = ba.newnode(
|
||||
'terrain',
|
||||
attrs={
|
||||
'model': self.preloaddata['bgmodel'],
|
||||
'lighting': False,
|
||||
'background': True,
|
||||
'color_texture': self.preloaddata['bgtex']
|
||||
})
|
||||
gnode = ba.getactivity().globalsnode
|
||||
gnode.tint = (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_inner = (0.9, 0.9, 0.9)
|
||||
gnode.vr_camera_offset = (0, -0.8, -1.1)
|
||||
gnode.vr_near_clip = 0.5
|
||||
|
||||
|
||||
|
||||
|
||||
ba._map.register_map(MGmap)
|
||||
307
dist/ba_root/mods/maps/VolleBallMap.py
vendored
Normal file
307
dist/ba_root/mods/maps/VolleBallMap.py
vendored
Normal file
|
|
@ -0,0 +1,307 @@
|
|||
|
||||
import ba,_ba
|
||||
from bastd.gameutils import SharedObjects
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Sequence, Optional, List, Dict, Type, Type , Union, Any, Literal
|
||||
|
||||
a=0.0
|
||||
class Pointzz:
|
||||
points, boxes = {}, {}
|
||||
points['ffa_spawn1'] = (-0.08016, 0.02275, -4.37367) + (8.89506, 0.05, 0.44435)
|
||||
points['ffa_spawn2'] = (-0.08016, 0.02275, 4.07629) + (8.89506, 0.05, 0.44435)
|
||||
points['flag1'] = (-10.72073, 0.06537, 0.14648)
|
||||
points['flag2'] = (10.7587, 0.04779, 0.14648)
|
||||
points['flag_default'] = (-0.10014, 0.0418, 0.10956)
|
||||
points['powerup_spawn1'] = (500000000.41468, 50000.9515, -500000.03791)
|
||||
points['powerup_spawn2'] = (-500000.5554, 500000.9515, -500000.03791)
|
||||
points['powerup_spawn3'] = (500000.41468, 50000.9515, 5000.14822)
|
||||
points['powerup_spawn4'] = (-50000.73727, 50000.9515, 500.14822)
|
||||
points['spawn1'] = (-8.03866, 0.02275, 0.0) + (0.5, 0.05, 4.0)
|
||||
points['spawn2'] = (8.82311, 0.01092, 0.0) + (0.5, 0.05, 4.0)
|
||||
boxes['area_of_interest_bounds'] = (0.0, 1.18575, 0.43262) + (0, 0, 0) + (29.81803, 11.57249, 18.89134)
|
||||
boxes['tnt1'] = (-0.10387, 0.41333, 0.42947) + (0, 0, 0) + (22.48296, 1.29024, 8.99025)
|
||||
boxes['goal1'] = (10,0.001,8)
|
||||
boxes['goal2'] = (10,0.001,8)
|
||||
boxes['map_bounds'] = (0.0, 1.185751251, 0.4326226188) + (0.0, 0.0, 0.0) + (
|
||||
42.09506485, 22.81173179, 29.76723155)
|
||||
|
||||
class PointzzforH:
|
||||
points, boxes = {}, {}
|
||||
boxes['area_of_interest_bounds'] = (0.0, 0.7956858119, 0.0) + (
|
||||
0.0, 0.0, 0.0) + (30.80223883, 0.5961646365, 13.88431707)
|
||||
points['ffa_spawn1'] = (-0.001925625146, 0.02305323209,
|
||||
-3.81971842) + (7.828121539, 1.0, 0.1588021252)
|
||||
points['ffa_spawn2'] = (-0.001925625146, 0.02305323209,
|
||||
3.560115735) + (7.828121539, 1.0, 0.05859841271)
|
||||
points['flag1'] = (-11.21689747, 0.09527878981, -0.07659307272)
|
||||
points['flag2'] = (11.08204909, 0.04119542459, -0.07659307272)
|
||||
points['flag_default'] = (-0.01690735171, 0.06139940044, -0.07659307272)
|
||||
boxes['goal1'] = (10,0.001,8)
|
||||
boxes['goal2'] = (10,0.001,8)
|
||||
boxes['map_bounds'] = (0.0, 0.7956858119, -0.4689020853) + (0.0, 0.0, 0.0) + (
|
||||
35.16182389, 12.18696164, 21.52869693)
|
||||
points['powerup_spawn1'] = (-3.654355317, 1.080990833, -4.765886164)
|
||||
points['powerup_spawn2'] = (-3.654355317, 1.080990833, 4.599802158)
|
||||
points['powerup_spawn3'] = (2.881071011, 1.080990833, -4.765886164)
|
||||
points['powerup_spawn4'] = (2.881071011, 1.080990833, 4.599802158)
|
||||
points['spawn1'] = (-6.835352227, 0.02305323209, 0.0) + (1.0, 1.0, 3.0)
|
||||
points['spawn2'] = (6.857415055, 0.03938567998, 0.0) + (1.0, 1.0, 3.0)
|
||||
points['tnt1'] = (-0.05791962398, 1.080990833, -4.765886164)
|
||||
|
||||
class VolleyBallMap(ba.Map):
|
||||
from VolleyBall import Pointzz as defs
|
||||
name = "Open Field"
|
||||
|
||||
@classmethod
|
||||
def get_play_types(cls) -> List[str]:
|
||||
"""Return valid play types for this map."""
|
||||
return []
|
||||
|
||||
@classmethod
|
||||
def get_preview_texture_name(cls) -> str:
|
||||
return 'footballStadiumPreview'
|
||||
|
||||
@classmethod
|
||||
def on_preload(cls) -> Any:
|
||||
data: Dict[str, Any] = {
|
||||
'model': ba.getmodel('footballStadium'),
|
||||
'vr_fill_model': ba.getmodel('footballStadiumVRFill'),
|
||||
'collide_model': ba.getcollidemodel('footballStadiumCollide'),
|
||||
'tex': ba.gettexture('footballStadium')
|
||||
}
|
||||
return data
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
shared = SharedObjects.get()
|
||||
|
||||
## Hey Quasi thx for looping these xD ##
|
||||
|
||||
|
||||
|
||||
x = -5
|
||||
while x<5:
|
||||
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(0,0,x),
|
||||
'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),
|
||||
'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),
|
||||
'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),
|
||||
'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),
|
||||
'color':(1,1,0),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
|
||||
x = x + 0.5
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
y = -1
|
||||
while y>-11:
|
||||
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(y,0.01,4),
|
||||
'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),
|
||||
'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),
|
||||
'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),
|
||||
'color':(1,0,0),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
|
||||
y-=1
|
||||
|
||||
|
||||
|
||||
z = 0
|
||||
while z<5:
|
||||
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(11,0.01,z),
|
||||
'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),
|
||||
'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),
|
||||
'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),
|
||||
'color':(0,0,1),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
|
||||
z+=1
|
||||
|
||||
|
||||
|
||||
self.node = ba.newnode(
|
||||
'terrain',
|
||||
delegate=self,
|
||||
attrs={
|
||||
'model': self.preloaddata['model'],
|
||||
'collide_model': self.preloaddata['collide_model'],
|
||||
'color_texture': self.preloaddata['tex'],
|
||||
'materials': [shared.footing_material]
|
||||
})
|
||||
ba.newnode('terrain',
|
||||
attrs={
|
||||
'model': self.preloaddata['vr_fill_model'],
|
||||
'lighting': False,
|
||||
'vr_only': True,
|
||||
'background': True,
|
||||
'color_texture': self.preloaddata['tex']
|
||||
})
|
||||
gnode = ba.getactivity().globalsnode
|
||||
gnode.tint = (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_inner = (0.9, 0.9, 0.9)
|
||||
gnode.vr_camera_offset = (0, -0.8, -1.1)
|
||||
gnode.vr_near_clip = 0.5
|
||||
|
||||
def is_point_near_edge(self,
|
||||
point: ba.Vec3,
|
||||
running: bool = False) -> bool:
|
||||
box_position = self.defs.boxes['edge_box'][0:3]
|
||||
box_scale = self.defs.boxes['edge_box'][6:9]
|
||||
xpos = (point.x - box_position[0]) / box_scale[0]
|
||||
zpos = (point.z - box_position[2]) / box_scale[2]
|
||||
return xpos < -0.5 or xpos > 0.5 or zpos < -0.5 or zpos > 0.5
|
||||
|
||||
class VolleyBallMapH(ba.Map):
|
||||
"""Stadium map used for ice hockey games."""
|
||||
|
||||
from VolleyBall import PointzzforH as defs
|
||||
name = 'Closed Arena'
|
||||
|
||||
@classmethod
|
||||
def get_play_types(cls) -> List[str]:
|
||||
"""Return valid play types for this map."""
|
||||
return []
|
||||
|
||||
@classmethod
|
||||
def get_preview_texture_name(cls) -> str:
|
||||
return 'hockeyStadiumPreview'
|
||||
|
||||
@classmethod
|
||||
def on_preload(cls) -> Any:
|
||||
data: Dict[str, Any] = {
|
||||
'models': (ba.getmodel('hockeyStadiumOuter'),
|
||||
ba.getmodel('hockeyStadiumInner')),
|
||||
'vr_fill_model': ba.getmodel('footballStadiumVRFill'),
|
||||
'collide_model': ba.getcollidemodel('hockeyStadiumCollide'),
|
||||
'tex': ba.gettexture('hockeyStadium'),
|
||||
}
|
||||
mat = ba.Material()
|
||||
mat.add_actions(actions=('modify_part_collision', 'friction', 0.01))
|
||||
data['ice_material'] = mat
|
||||
return data
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
shared = SharedObjects.get()
|
||||
|
||||
## Hey Quasi thx for looping these xD ##
|
||||
|
||||
|
||||
x = -5
|
||||
while x<5:
|
||||
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(0,0,x),
|
||||
'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),
|
||||
'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),
|
||||
'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),
|
||||
'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),
|
||||
'color':(1,1,0),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
|
||||
x = x + 0.5
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
y = -1
|
||||
while y>-11:
|
||||
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(y,0.01,4),
|
||||
'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),
|
||||
'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),
|
||||
'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),
|
||||
'color':(1,0,0),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
|
||||
y-=1
|
||||
|
||||
|
||||
|
||||
z = 0
|
||||
while z<5:
|
||||
self.zone = ba.newnode('locator',attrs={'shape':'circle','position':(11,0.01,z),
|
||||
'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),
|
||||
'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),
|
||||
'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),
|
||||
'color':(0,0,1),'opacity':1,'draw_beauty':True,'additive':False,'size':[0.40]})
|
||||
z+=1
|
||||
|
||||
|
||||
|
||||
self.node = ba.newnode('terrain',
|
||||
delegate=self,
|
||||
attrs={
|
||||
'model':
|
||||
None,
|
||||
'collide_model':
|
||||
ba.getcollidemodel('footballStadiumCollide'), ## we dont want Goalposts...
|
||||
'color_texture':
|
||||
self.preloaddata['tex'],
|
||||
'materials': [
|
||||
shared.footing_material]
|
||||
})
|
||||
ba.newnode('terrain',
|
||||
attrs={
|
||||
'model': self.preloaddata['vr_fill_model'],
|
||||
'vr_only': True,
|
||||
'lighting': False,
|
||||
'background': True,
|
||||
})
|
||||
mats = [shared.footing_material]
|
||||
self.floor = ba.newnode('terrain',
|
||||
attrs={
|
||||
'model': self.preloaddata['models'][1],
|
||||
'color_texture': self.preloaddata['tex'],
|
||||
'opacity': 0.92,
|
||||
'opacity_in_low_or_medium_quality': 1.0,
|
||||
'materials': mats,
|
||||
'color': (0.4,0.9,0)
|
||||
})
|
||||
|
||||
self.background = ba.newnode(
|
||||
'terrain',
|
||||
attrs={
|
||||
'model': ba.getmodel('natureBackground'),
|
||||
'lighting': False,
|
||||
'background': True,
|
||||
'color': (0.5,0.30,0.4)
|
||||
})
|
||||
|
||||
gnode = ba.getactivity().globalsnode
|
||||
gnode.floor_reflection = True
|
||||
gnode.debris_friction = 0.3
|
||||
gnode.debris_kill_height = -0.3
|
||||
gnode.tint = (1.2, 1.3, 1.33)
|
||||
gnode.ambient_color = (1.15, 1.25, 1.6)
|
||||
gnode.vignette_outer = (0.66, 0.67, 0.73)
|
||||
gnode.vignette_inner = (0.93, 0.93, 0.95)
|
||||
gnode.vr_camera_offset = (0, -0.8, -1.1)
|
||||
gnode.vr_near_clip = 0.5
|
||||
#self.is_hockey = True
|
||||
|
||||
|
||||
## Plugin only for our dirty map UwU ##
|
||||
|
||||
ba._map.register_map(VolleyBallMap)
|
||||
ba._map.register_map(VolleyBallMapH)
|
||||
98
dist/ba_root/mods/maps/WoodenFloor.py
vendored
Normal file
98
dist/ba_root/mods/maps/WoodenFloor.py
vendored
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import ba,_ba
|
||||
from bastd.gameutils import SharedObjects
|
||||
from bastd.actor.playerspaz import PlayerSpaz
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, List, Dict
|
||||
|
||||
|
||||
class WoodenFloor(ba.Map):
|
||||
"""Stadium map for football games."""
|
||||
from bastd.mapdata import football_stadium as defs
|
||||
defs.points['spawn1'] = (-12.03866341, 0.02275111462, 0.0) + (0.5, 1.0, 4.0)
|
||||
defs.points['spawn2'] = (12.823107149, 0.01092306765, 0.0) + (0.5, 1.0, 4.0)
|
||||
name = 'Wooden Floor'
|
||||
|
||||
@classmethod
|
||||
def get_play_types(cls) -> list[str]:
|
||||
"""Return valid play types for this map."""
|
||||
return ['melee', 'football', 'team_flag', 'keep_away']
|
||||
|
||||
@classmethod
|
||||
def get_preview_texture_name(cls) -> str:
|
||||
return 'footballStadiumPreview'
|
||||
|
||||
@classmethod
|
||||
def on_preload(cls) -> Any:
|
||||
data: dict[str, Any] = {
|
||||
|
||||
'model_bg': ba.getmodel('doomShroomBG'),
|
||||
'bg_vr_fill_model': ba.getmodel('natureBackgroundVRFill'),
|
||||
'collide_model': ba.getcollidemodel('bridgitLevelCollide'),
|
||||
'tex': ba.gettexture('bridgitLevelColor'),
|
||||
'model_bg_tex': ba.gettexture('doomShroomBGColor'),
|
||||
'collide_bg': ba.getcollidemodel('natureBackgroundCollide'),
|
||||
'railing_collide_model':
|
||||
(ba.getcollidemodel('bridgitLevelRailingCollide')),
|
||||
'bg_material': ba.Material()
|
||||
}
|
||||
data['bg_material'].add_actions(actions=('modify_part_collision',
|
||||
'friction', 10.0))
|
||||
return data
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
shared = SharedObjects.get()
|
||||
self.background = ba.newnode(
|
||||
'terrain',
|
||||
attrs={
|
||||
'model': self.preloaddata['model_bg'],
|
||||
'lighting': False,
|
||||
'background': True,
|
||||
'color_texture': self.preloaddata['model_bg_tex']
|
||||
})
|
||||
ba.newnode('terrain',
|
||||
attrs={
|
||||
'model': self.preloaddata['bg_vr_fill_model'],
|
||||
'lighting': False,
|
||||
'vr_only': True,
|
||||
'background': True,
|
||||
'color_texture': self.preloaddata['model_bg_tex']
|
||||
})
|
||||
gnode = ba.getactivity().globalsnode
|
||||
gnode.tint = (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_inner = (0.9, 0.9, 0.9)
|
||||
gnode.vr_camera_offset = (0, -0.8, -1.1)
|
||||
gnode.vr_near_clip = 0.5
|
||||
# self.map_extend()
|
||||
|
||||
def is_point_near_edge(self,
|
||||
point: ba.Vec3,
|
||||
running: bool = False) -> bool:
|
||||
box_position = self.defs.boxes['edge_box'][0:3]
|
||||
box_scale = self.defs.boxes['edge_box'][6:9]
|
||||
xpos = (point.x - box_position[0]) / box_scale[0]
|
||||
zpos = (point.z - box_position[2]) / box_scale[2]
|
||||
return xpos < -0.5 or xpos > 0.5 or zpos < -0.5 or zpos > 0.5
|
||||
|
||||
|
||||
def _handle_player_collide(self):
|
||||
try:
|
||||
player = ba.getcollision().opposingnode.getdelegate(
|
||||
PlayerSpaz, True)
|
||||
except ba.NotFoundError:
|
||||
return
|
||||
|
||||
|
||||
if player.is_alive():
|
||||
player.shatter(True)
|
||||
|
||||
|
||||
|
||||
|
||||
ba._map.register_map(WoodenFloor)
|
||||
334
dist/ba_root/mods/maps/baMaps_v1.py
vendored
Normal file
334
dist/ba_root/mods/maps/baMaps_v1.py
vendored
Normal file
|
|
@ -0,0 +1,334 @@
|
|||
# ba_meta require api 6
|
||||
|
||||
# Plugin SEBASTIAN2059 - Zacker Tz
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# - Maps: -
|
||||
# - Neo Zone - by Zacker Tz || Zacker#5505 -
|
||||
# - Big H map - by SEBASTIAN2059 || SEBASTIAN2059#5751 -
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from bastd.maps import *
|
||||
import ba
|
||||
import _ba
|
||||
import base64
|
||||
from ba import _map
|
||||
import random
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, List, Dict
|
||||
|
||||
#Map by Zacker Tz
|
||||
class neo_defs():
|
||||
boxes = {}
|
||||
points = {}
|
||||
boxes['area_of_interest_bounds'] = (0, 4, 0) + (0, 0, 0) + (50, 10, 20)
|
||||
boxes['edge_box'] = (0, 4, 0) + (0.0, 0.0, 0.0) + (40, 2, 10)
|
||||
boxes['map_bounds'] = (0, 4, 0) + (0, 0, 0) + (28, 10, 28)
|
||||
points['ffa_spawn1'] = (-10,3.17,0) + (1.0,0.1,1.0)
|
||||
points['ffa_spawn2'] = (10,3.17,0) + (1.0,0.1,1.0)
|
||||
points['ffa_spawn3'] = (-5.25,3.17,-1.75) + (0.5,0.1,0.5)
|
||||
points['ffa_Spawn4'] = (5.25,3.17,-1.75) + (0.5,0.1,0.5)
|
||||
points['spawn1'] = (-11,3.17,0) + (1.0,0.1,1.0)
|
||||
points['spawn2'] = (11,3.17,0) + (1.0,0.1,1.0)
|
||||
points['flag1'] = (-12.0,3.3,0) + (2.0,0.1,2.0)
|
||||
points['flag2'] = (12.0,3.3,0) + (2.0,0.1,2.0)
|
||||
points['flag_default'] = (0,3.3,1.75)
|
||||
points['powerup_spawn1'] = (-11,4.0,-1.75)
|
||||
points['powerup_spawn2'] = (-11,4.0,1.75)
|
||||
points['powerup_spawn3'] = (-1.75,4.0,0)
|
||||
points['powerup_spawn4'] = (1.75,4.0,0.0)
|
||||
points['powerup_spawn5'] = (11,4.0,-1.75)
|
||||
points['powerup_spawn6'] = (11,4.0,1.75)
|
||||
|
||||
|
||||
class NeoZone(ba.Map):
|
||||
"""Agent john's former workplace"""
|
||||
|
||||
defs = neo_defs()
|
||||
name = 'Neo Zone'
|
||||
|
||||
@classmethod
|
||||
def get_play_types(cls) -> List[str]:
|
||||
"""Return valid play types for this map."""
|
||||
return ['melee','king_of_the_hill','keep_away','team_flag']
|
||||
|
||||
@classmethod
|
||||
def get_preview_texture_name(cls) -> str:
|
||||
return 'rgbStripes'
|
||||
|
||||
@classmethod
|
||||
def on_preload(cls) -> Any:
|
||||
data: Dict[str, Any] = {
|
||||
'model': ba.getmodel('landMine'),
|
||||
'tex': ba.gettexture('landMine'),
|
||||
'bgtex': ba.gettexture('black'),
|
||||
'bgmodel': ba.getmodel('thePadBG'),
|
||||
}
|
||||
return data
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
shared = SharedObjects.get()
|
||||
|
||||
self._collide_with_player=ba.Material()
|
||||
self._collide_with_player.add_actions(conditions=('we_are_older_than', 1), actions=(('modify_part_collision', 'collide', True)))
|
||||
self.dont_collide=ba.Material()
|
||||
self.dont_collide.add_actions(conditions=('they_are_different_node_than_us', ),actions=(('modify_part_collision', 'collide', False)))
|
||||
|
||||
self._map_model = ba.getmodel('image1x1')
|
||||
self._map_model2 = ba.getmodel('tnt')
|
||||
self._map_tex = ba.gettexture('powerupIceBombs')
|
||||
self._map_tex1 = ba.gettexture('ouyaUButton')
|
||||
|
||||
self.background = ba.newnode('terrain',
|
||||
attrs={
|
||||
'model': self.preloaddata['bgmodel'],
|
||||
'lighting': False,
|
||||
'background': True,
|
||||
'color_texture': self.preloaddata['bgtex']
|
||||
})
|
||||
|
||||
locations = [(7.0,0.0,0),(5.25,0.0,0),(5.25,0.0,-1.75),
|
||||
(3.5,0.0,-1.75),(1.75,0.0,-1.75),(1.75,0.0,0),
|
||||
(1.75,0.0,1.75),
|
||||
(0,0.0,1.75),
|
||||
(-7.0,0.0,0),(-5.25,0.0,0),(-5.25,3.17,-1.75),
|
||||
(-3.5,0.0,-1.75),(-1.75,0.0,-1.75),(-1.75,0.0,0),
|
||||
(-1.75,0.0,1.75)]
|
||||
num = 0
|
||||
|
||||
for pos in locations:
|
||||
color = (0,1,0) if num in [0,1,5,8,9,13] else (0,0,1) if num in [6,7,14] else (1,0,0) if num in [2,3,4,10,11,12] else (1,1,1)
|
||||
self.decor = ba.newnode('prop',
|
||||
attrs={'body': 'puck',
|
||||
'position': (pos[0],3.17,pos[2]),
|
||||
'model': self._map_model,
|
||||
'model_scale': 1.7,
|
||||
'body_scale': 0.1,
|
||||
'shadow_size': 0.0,
|
||||
'gravity_scale':0.0,
|
||||
'color_texture': self._map_tex1,
|
||||
'reflection': 'soft',
|
||||
'reflection_scale': [0.5],
|
||||
'is_area_of_interest': True,
|
||||
'materials': [self.dont_collide]})
|
||||
self.region = ba.newnode('region',attrs={
|
||||
'position': (pos[0],2.3,pos[2]),
|
||||
'scale': (1.9,1.9,1.9),
|
||||
'type': 'box',
|
||||
'materials': (self._collide_with_player, shared.footing_material)})
|
||||
self.zone = ba.newnode('locator',
|
||||
attrs={'shape':'box',
|
||||
'position':(pos[0],2.3,pos[2]),
|
||||
'color':color,
|
||||
'opacity':1,'draw_beauty':True,'additive':False,'size':[1.75,1.75,1.75]})
|
||||
num += 1
|
||||
|
||||
#Sides
|
||||
side_locations = [(-10.5,2.3,0),(10.5,2.3,0)]
|
||||
for pos in side_locations:
|
||||
self.big_region = ba.newnode('region',attrs={
|
||||
'position': pos,
|
||||
'scale': (5.7,1.9,5.7),
|
||||
'type': 'box',
|
||||
'materials': (self._collide_with_player, shared.footing_material)})
|
||||
self.big_zone = ba.newnode('locator',
|
||||
attrs={'shape':'box',
|
||||
'position':pos,
|
||||
'color':(0,1,1.5),
|
||||
'opacity':1,'draw_beauty':True,'additive':False,'size':[5.25,1.75,5.25]})
|
||||
|
||||
exec(base64.b64decode("dCA9IGJhLm5ld25vZGUoJ3RleHQnLAogICAgICAgICAgICAgICBhdHRycz17ICd0ZXh0JzoiTWFwYXMgcG9yOiBTRUJBU1RJQU4yMDU5IHkgWmFja2VyIERDIiwgCiAgICAgICAgJ3NjYWxlJzowLjYsCiAgICAgICAgJ3Bvc2l0aW9uJzooMCwwKSwgCiAgICAgICAgJ29wYWNpdHknOiAwLjQsCiAgICAgICAgJ3NoYWRvdyc6MC41LAogICAgICAgICdmbGF0bmVzcyc6MS4yLAogICAgICAgICdjb2xvcic6KDEsIDEsIDEpLAogICAgICAgICdoX2FsaWduJzonY2VudGVyJywKICAgICAgICAndl9hdHRhY2gnOidib3R0b20nfSk=").decode('UTF-8')) #bubalu
|
||||
|
||||
gnode = ba.getactivity().globalsnode
|
||||
gnode.tint = (1.1, 1.05, 1.17)
|
||||
gnode.happy_thoughts_mode = False
|
||||
gnode.ambient_color = (1.2, 1.17, 1.1)
|
||||
gnode.vignette_outer = (0.9, 0.9, 0.96)
|
||||
gnode.vignette_inner = (0.95, 0.95, 0.93)
|
||||
|
||||
#Map by Sebastian2059
|
||||
class c_defs():
|
||||
boxes = {}
|
||||
points = {}
|
||||
boxes['area_of_interest_bounds'] = (0, 4, 0) + (0, 0, 0) + (50, 10, 20)
|
||||
boxes['edge_box'] = (0, 4, 0) + (0.0, 0.0, 0.0) + (40, 2, 10)
|
||||
boxes['map_bounds'] = (0, 4, 0) + (0, 0, 0) + (28, 10, 28)
|
||||
points['ffa_spawn1'] = (-9,0.5,-3) + (1.0,0.1,5.0)
|
||||
points['ffa_spawn2'] = (9,0.5,-3) + (1.0,0.1,5.0)
|
||||
points['ffa_spawn3'] = (-6,0.5,-6.0) + (2.0,0.1,1.0)
|
||||
points['ffa_Spawn4'] = (6,0.5,0.0) + (2.0,0.1,1.0)
|
||||
points['ffa_spawn5'] = (6,0.5,-6.0) + (2.0,0.1,1.0)
|
||||
points['ffa_Spawn6'] = (-6,0.5,0.0) + (2.0,0.1,1.0)
|
||||
points['spawn1'] = (-9,0.5,-3) + (1.0,0.1,1.0)
|
||||
points['spawn2'] = (9,0.5,-3) + (1.0,0.1,1.0)
|
||||
points['flag1'] = (-10.0,0.8,-3) + (2.0,0.1,2.0)
|
||||
points['flag2'] = (10.0,0.8,-3) + (2.0,0.1,2.0)
|
||||
points['flag_default'] = (0,0.8,-3.0)
|
||||
points['powerup_spawn1'] = (-9,1.0,-8)
|
||||
points['powerup_spawn2'] = (-9,1.0,3)
|
||||
points['powerup_spawn3'] = (-1.5,1.0,-8.25)
|
||||
points['powerup_spawn4'] = (1.5,1.0,-8.25)
|
||||
points['powerup_spawn5'] = (-1.5,1.0,2.25)
|
||||
points['powerup_spawn6'] = (1.5,1.0,2.25)
|
||||
points['powerup_spawn7'] = (9,1.0,-8)
|
||||
points['powerup_spawn8'] = (9,1.0,3)
|
||||
|
||||
points['race_mine1'] = (-1.5, 0.7, -0.7)
|
||||
points['race_mine2'] = (-1.5, 0.7, 0.7)
|
||||
points['race_mine3'] = (-4.5, 0.7, 0.0)
|
||||
points['race_mine4'] = (4.5, 0.7, 0.0)
|
||||
points['race_mine5'] = (4.5, 0.7, -6.0)
|
||||
points['race_mine6'] = (-4.5, 0.7, -6.0)
|
||||
points['race_mine7'] = (0.0, 0.7, -6.0)
|
||||
points['race_mine8'] = (-10.0, 0.7, -4.5)
|
||||
points['race_mine9'] = (10.0, 0.7, -4.5)
|
||||
points['race_mine10'] = (10.0, 0.7, -1.5)
|
||||
points['race_mine11'] = (-10.0, 0.7, -1.5)
|
||||
|
||||
points['race_point1'] = (0.0, 0.5, 0.0) + (0.3, 2.0, 1.5)
|
||||
points['race_point2'] = (3.5, 0.5, 0.0) + (0.3, 2.0, 1.5)
|
||||
points['race_point3'] = (7.0, 0.5, 0.0) + (0.3, 2.0, 1.5)
|
||||
points['race_point4'] = (9.0, 0.5, -2.0) + (1.5, 2.0, 0.3)
|
||||
points['race_point5'] = (9.0, 0.5, -4.0) + (1.5, 2.0, 0.3)
|
||||
points['race_point6'] = (7.0, 0.5, -6.0) + (0.3, 2.0, 1.5)
|
||||
points['race_point7'] = (3.5, 0.5, -6.0) + (0.3, 2.0, 1.5)
|
||||
points['race_point8'] = (0.0, 0.5, -6.0) + (0.3, 2.0, 1.5)
|
||||
points['race_point9'] = (-3.5, 0.5, -6.0) + (0.3, 2.0, 1.5)
|
||||
points['race_point10'] = (-7.0, 0.5, -6.0) + (0.3, 2.0, 1.5)
|
||||
points['race_point11'] = (-9.0, 0.5, -2.0) + (1.5, 2.0, 0.3)
|
||||
points['race_point12'] = (-9.0, 0.5, -4.0) + (1.5, 2.0, 0.3)
|
||||
points['race_point13'] = (-7.0, 0.5, 0.0) + (0.3, 2.0, 1.5)
|
||||
points['race_point14'] = (-3.5, 0.5, 0.0) + (0.3, 2.0, 1.5)
|
||||
|
||||
class CMap(ba.Map):
|
||||
"""Jack Morgan used to run here"""
|
||||
|
||||
defs = c_defs()
|
||||
name = 'Big H'
|
||||
|
||||
@classmethod
|
||||
def get_play_types(cls) -> List[str]:
|
||||
"""Return valid play types for this map."""
|
||||
return ['melee','king_of_the_hill','keep_away','team_flag','race']
|
||||
|
||||
@classmethod
|
||||
def get_preview_texture_name(cls) -> str:
|
||||
return 'bigG'
|
||||
|
||||
@classmethod
|
||||
def on_preload(cls) -> Any:
|
||||
data: Dict[str, Any] = {
|
||||
'model': ba.getmodel('landMine'),
|
||||
'tex': ba.gettexture('landMine'),
|
||||
'bgtex': ba.gettexture('black'),
|
||||
'bgmodel': ba.getmodel('thePadBG'),
|
||||
}
|
||||
return data
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
shared = SharedObjects.get()
|
||||
|
||||
self._collide_with_player=ba.Material()
|
||||
self._collide_with_player.add_actions(conditions=('we_are_older_than', 1), actions=(('modify_part_collision', 'collide', True)))
|
||||
self.dont_collide=ba.Material()
|
||||
self.dont_collide.add_actions(conditions=('they_are_different_node_than_us', ),actions=(('modify_part_collision', 'collide', False)))
|
||||
self.ice_material = ba.Material()
|
||||
self.ice_material.add_actions(actions=('modify_part_collision','friction',0.01))
|
||||
|
||||
self._map_model = ba.getmodel('image1x1')
|
||||
self._map_model2 = ba.getmodel('tnt')
|
||||
self._map_tex = ba.gettexture('powerupIceBombs')
|
||||
self._map_tex1 = ba.gettexture('circleOutlineNoAlpha')
|
||||
self._map_tex2 = ba.gettexture('black')
|
||||
|
||||
self.background = ba.newnode('terrain',
|
||||
attrs={
|
||||
'model': self.preloaddata['bgmodel'],
|
||||
'lighting': False,
|
||||
'background': True,
|
||||
'color_texture': self.preloaddata['bgtex']
|
||||
})
|
||||
|
||||
posS = [(0.0,0.05,0)]
|
||||
for m_pos in posS:
|
||||
self.mv_center = ba.newnode('prop',
|
||||
attrs={'body': 'puck',
|
||||
'position': m_pos,
|
||||
'model': self._map_model,
|
||||
'model_scale': 35,
|
||||
'body_scale': 0.1,
|
||||
'shadow_size': 0.0,
|
||||
'gravity_scale':0.0,
|
||||
'color_texture': self._map_tex2,
|
||||
'reflection': 'soft',
|
||||
'reflection_scale': [0],
|
||||
'is_area_of_interest': True,
|
||||
'materials': [self.dont_collide]})
|
||||
try:
|
||||
self._gamemode = ba.getactivity().name
|
||||
except Exception:
|
||||
print('error')
|
||||
pass
|
||||
locations = [(-9,0.0,-3.0),(9,0.0,-3.0),(0.0,0.0,0.0),(0.0,0.0,-6.0),(0.0,0.0,-3.0)]
|
||||
scales = [[3.0,1.0,14.0],[3.0,1.0,14.0],[15.0,1.0,3.0],[15.0,1.0,3.0],[3.0,1.0,3.0]]
|
||||
index = 0
|
||||
for pos in locations:
|
||||
#
|
||||
scale = scales[index]
|
||||
ba.newnode('region',attrs={'position': pos,'scale': scale,'type': 'box','materials': (self._collide_with_player, shared.footing_material)})
|
||||
ba.newnode('locator',attrs={'shape':'box','position':pos,
|
||||
'color':(1,1,1),'opacity':1, 'drawShadow':False,'draw_beauty':True,'additive':False,'size':scale})
|
||||
index += 1
|
||||
|
||||
pos = [-3.0,0.0,-8.25]
|
||||
for p in range(10):
|
||||
scale = [1.5,1.0,1.5]
|
||||
ba.newnode('region',attrs={'position': pos,'scale': scale,'type': 'box','materials': (self._collide_with_player, shared.footing_material)})
|
||||
ba.newnode('locator',attrs={'shape':'box','position':pos,
|
||||
'color':(1,1,1),'opacity':1, 'drawShadow':False,'draw_beauty':True,'additive':False,'size':scale})
|
||||
pos[0] += 1.5
|
||||
if p == 4:
|
||||
pos[0] = -3.0
|
||||
pos[2] = 2.25
|
||||
|
||||
if self._gamemode == 'Race':
|
||||
ice_locations = [(-8,0.0,0),(8,0.0,0),
|
||||
(-8,0.0,-6),(8,0.0,-6),
|
||||
(-9,0.0,-3),(9,0.0,-3)]
|
||||
|
||||
for pos in ice_locations:
|
||||
scale = [3.0,1.025,3.0]
|
||||
ba.newnode('region',attrs={'position': pos,'scale': scale,'type': 'box','materials': (self._collide_with_player, shared.footing_material, self.ice_material)})
|
||||
ba.newnode('locator',attrs={'shape':'box','position':pos,
|
||||
'color':(0,1,1),'opacity':1, 'drawShadow':False,'draw_beauty':True,'additive':False,'size':scale})
|
||||
|
||||
exec(base64.b64decode("dCA9IGJhLm5ld25vZGUoJ3RleHQnLAogICAgICAgICAgICAgICBhdHRycz17ICd0ZXh0JzoiTWFwYXMgcG9yOiBTRUJBU1RJQU4yMDU5IHkgWmFja2VyIERDIiwgCiAgICAgICAgJ3NjYWxlJzowLjYsCiAgICAgICAgJ3Bvc2l0aW9uJzooMCwwKSwgCiAgICAgICAgJ29wYWNpdHknOiAwLjQsCiAgICAgICAgJ3NoYWRvdyc6MC41LAogICAgICAgICdmbGF0bmVzcyc6MS4yLAogICAgICAgICdjb2xvcic6KDEsIDEsIDEpLAogICAgICAgICdoX2FsaWduJzonY2VudGVyJywKICAgICAgICAndl9hdHRhY2gnOidib3R0b20nfSk=").decode('UTF-8')) #saludo
|
||||
|
||||
gnode = ba.getactivity().globalsnode
|
||||
gnode.tint = (1.1, 1.05, 1.17)
|
||||
gnode.happy_thoughts_mode = False
|
||||
gnode.ambient_color = (1.2, 1.17, 1.1)
|
||||
gnode.vignette_outer = (0.9, 0.9, 0.96)
|
||||
gnode.vignette_inner = (0.95, 0.95, 0.93)
|
||||
|
||||
#List Maps
|
||||
zk2059 = [NeoZone,CMap]
|
||||
|
||||
def register_maps():
|
||||
for new_map in zk2059:
|
||||
_map.register_map(new_map)
|
||||
|
||||
# ba_meta export plugin
|
||||
class Zk2059(ba.Plugin):
|
||||
def __init__(self):
|
||||
if _ba.env().get("build_number", 0) >= 20258:
|
||||
register_maps()
|
||||
else:
|
||||
print("new_maps.py only runs with BombSquad versions higher than 1.5.29.")
|
||||
|
||||
416
dist/ba_root/mods/maps/new_maps.py
vendored
Normal file
416
dist/ba_root/mods/maps/new_maps.py
vendored
Normal file
|
|
@ -0,0 +1,416 @@
|
|||
## DECODED FOR MODIFICATIONS OF MAP POINTS ##
|
||||
## DON'T SHARE ##
|
||||
|
||||
|
||||
# ba_meta require api 6
|
||||
|
||||
#Mod by Froshlee14
|
||||
#Updated by SEBASTIAN2059
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
|
||||
import ba
|
||||
import _ba
|
||||
import random
|
||||
from bastd.gameutils import SharedObjects
|
||||
from bastd.actor.powerupbox import PowerupBox, PowerupBoxFactory
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, List, Dict
|
||||
|
||||
|
||||
class mega_mine_defs:
|
||||
boxes = {}
|
||||
points = {}
|
||||
boxes['area_of_interest_bounds'] = (0, 1, 0) + (0, 0, 0) + (0, 0, 0)
|
||||
boxes['map_bounds'] = (0, 0, 0) + (0, 0, 0) + (20, 20, 20)
|
||||
points['ffa_spawn1'] = (3,2,-2)
|
||||
points['ffa_spawn2'] = (-3,2,-2)
|
||||
points['ffa_spawn3'] = (3,2,2)
|
||||
points['ffa_Spawn4'] = (-3,2,2)
|
||||
points['powerup_spawn1'] = (-2.8,3,0)
|
||||
points['powerup_spawn2'] = (2.8,3,0)
|
||||
points['powerup_spawn3'] = (0,3,-2.8)
|
||||
points['powerup_spawn4'] = (0,3,2.8)
|
||||
|
||||
|
||||
class MegaMine(ba.Map):
|
||||
"""A giant mine!"""
|
||||
|
||||
from new_maps import mega_mine_defs as defs
|
||||
|
||||
name = 'Mega Mine'
|
||||
|
||||
@classmethod
|
||||
def get_play_types(cls) -> List[str]:
|
||||
"""Return valid play types for this map."""
|
||||
return ['melee']
|
||||
|
||||
@classmethod
|
||||
def get_preview_texture_name(cls) -> str:
|
||||
return 'landMine'
|
||||
|
||||
@classmethod
|
||||
def on_preload(cls) -> Any:
|
||||
data: Dict[str, Any] = {
|
||||
'model': ba.getmodel('landMine'),
|
||||
'tex': ba.gettexture('landMine'),
|
||||
'bgtex': ba.gettexture('menuBG'),
|
||||
'bgmodel': ba.getmodel('thePadBG'),
|
||||
}
|
||||
return data
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
shared = SharedObjects.get()
|
||||
self.node = ba.newnode('prop',
|
||||
delegate=self,
|
||||
attrs={'position':(0,1,0),
|
||||
'velocity':(0,0,0),
|
||||
'model':self.preloaddata['model'],
|
||||
'size':[25,13,4],
|
||||
'model_scale':14.6,
|
||||
'body_scale':14.3,
|
||||
'density':999999999999999999999,
|
||||
'damping':999999999999999999999,
|
||||
'gravity_scale':0,
|
||||
'body':'landMine',
|
||||
'reflection':'powerup',
|
||||
'reflection_scale':[1.0],
|
||||
'color_texture':self.preloaddata['tex'],
|
||||
'materials':[shared.footing_material]})
|
||||
|
||||
|
||||
self.background = ba.newnode('terrain',
|
||||
attrs={
|
||||
'model': self.preloaddata['bgmodel'],
|
||||
'lighting': False,
|
||||
'background': True,
|
||||
'color_texture': self.preloaddata['bgtex']
|
||||
})
|
||||
|
||||
gnode = ba.getactivity().globalsnode
|
||||
gnode.tint = (1.2, 1.17, 1.1)
|
||||
gnode.ambient_color = (1.2, 1.17, 1.1)
|
||||
gnode.vignette_outer = (0.6, 0.6, 0.64)
|
||||
gnode.vignette_inner = (0.95, 0.95, 0.93)
|
||||
|
||||
|
||||
class powerups_defs:
|
||||
boxes = {}
|
||||
points = {}
|
||||
boxes['area_of_interest_bounds'] = (0, -2, -2) + (0, 0, 0) + (0, 15, 0)
|
||||
boxes['map_bounds'] = (0, 1, 0) + (0, -3, 0) + (50, 30, 50)
|
||||
points['ffa_spawn1'] = (3,2,-1.5)
|
||||
points['ffa_spawn2'] = (-3,2,-1.5)
|
||||
points['ffa_spawn3'] = (3,2,1.5)
|
||||
points['ffa_spawn4'] = (-3,2,1.5)
|
||||
points['powerup_spawn1'] = (-2,3,0)
|
||||
points['powerup_spawn2'] = (2,3,0)
|
||||
|
||||
|
||||
class PowerupMap(ba.Map):
|
||||
"""A Powerups!"""
|
||||
|
||||
from new_maps import powerups_defs as defs
|
||||
|
||||
name = 'Powerups'
|
||||
|
||||
@classmethod
|
||||
def get_play_types(cls) -> List[str]:
|
||||
"""Return valid play types for this map."""
|
||||
return ['melee']
|
||||
|
||||
@classmethod
|
||||
def get_preview_texture_name(cls) -> str:
|
||||
return 'powerupShield'
|
||||
|
||||
@classmethod
|
||||
def on_preload(cls) -> Any:
|
||||
data: Dict[str, Any] = {
|
||||
'bgtex': ba.gettexture('menuBG'),
|
||||
'bgmodel': ba.getmodel('thePadBG'),
|
||||
}
|
||||
return data
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
shared = SharedObjects.get()
|
||||
Box(position=(-3,-2,0),texture='powerupShield')
|
||||
Box(position=(3,-2,0),texture='powerupSpeed')
|
||||
Box(position=(-3,-7,0),texture='powerupHealth')
|
||||
Box(position=(3,-7,0),texture='powerupCurse')
|
||||
|
||||
self._new_region_material = ba.Material()
|
||||
self._new_region_material.add_actions(
|
||||
conditions=('they_have_material', shared.object_material),
|
||||
actions=(('modify_part_collision', 'collide',
|
||||
True), ('modify_part_collision', 'physical', False)))
|
||||
|
||||
self._region = ba.newnode('region',
|
||||
attrs={
|
||||
'position': (2,-10.5,0),
|
||||
'scale': (18, 0, 12),
|
||||
'type': 'box',
|
||||
'materials': [self._new_region_material, shared.death_material]
|
||||
})
|
||||
# a = ba.newnode('locator',attrs={'shape':'box','position':(0,-10.5,0),
|
||||
# 'color':(1,1,1),'opacity':1, 'drawShadow':False,'draw_beauty':True,'additive':False,'size':[18,0,12]})
|
||||
|
||||
self._call_powerups = ba.timer(0.1,ba.Call(self.spawn_powerup),repeat=True)
|
||||
|
||||
self.background = ba.newnode('terrain',
|
||||
attrs={
|
||||
'model': self.preloaddata['bgmodel'],
|
||||
'lighting': False,
|
||||
'background': True,
|
||||
'color_texture': self.preloaddata['bgtex']
|
||||
})
|
||||
|
||||
gnode = ba.getactivity().globalsnode
|
||||
gnode.tint = (1.0,1.0,1.0)
|
||||
gnode.ambient_color = (1.1,1.1,1.0)
|
||||
gnode.vignette_outer = (0.7,0.65,0.75)
|
||||
gnode.vignette_inner = (0.95,0.95,0.93)
|
||||
|
||||
def spawn_powerup(self):
|
||||
pos = (-15+random.random()*30,-13,-15+random.random()*30)
|
||||
if not random.random() > 0.9997:
|
||||
p = PowerupBox(position=pos,poweruptype=PowerupBoxFactory().get_random_powerup_type(),expire=False).autoretain()
|
||||
p.node.gravity_scale = -0.1
|
||||
|
||||
|
||||
class Box(ba.Actor):
|
||||
def __init__(self,position=(0,0,0),texture=None):
|
||||
ba.Actor.__init__(self)
|
||||
shared = SharedObjects.get()
|
||||
self.node = ba.newnode('prop',
|
||||
delegate=self,
|
||||
attrs={'position':position,
|
||||
'velocity':(0,0,0),
|
||||
'model':ba.getmodel('powerup'),
|
||||
'model_scale':8.6,
|
||||
'body_scale':7 ,
|
||||
'density':999999999999999999999,
|
||||
'damping':999999999999999999999,
|
||||
'gravity_scale':0,
|
||||
'body':'crate',
|
||||
'reflection':'powerup',
|
||||
'reflection_scale':[0.3],
|
||||
'color_texture':ba.gettexture(texture),
|
||||
'materials':[shared.footing_material]})
|
||||
|
||||
|
||||
|
||||
class darkness_defs:
|
||||
boxes = {}
|
||||
points = {}
|
||||
boxes['area_of_interest_bounds'] = (0, 1, 0) + (0, 0, 0) + (17, 0, 0)
|
||||
boxes['map_bounds'] = (0, 0, 0) + (0, 0, 0) + (10.5, 20, 10.5)
|
||||
points['flag_default'] = (0,1,0)
|
||||
points['flag1'] = (-4.7,1,0)
|
||||
points['spawn1'] = (-4.7,1,0)
|
||||
points['flag2'] = (4.7,1,0)
|
||||
points['spawn2'] = (4.7,1,0)
|
||||
points['ffa_spawn1'] = (0,1,3)
|
||||
points['ffa_spawn2'] = (0,1,-3)
|
||||
points['ffa_spawn3'] = (3,1,0)
|
||||
points['ffa_spawn4'] = (-3,1,0)
|
||||
points['powerup_spawn1'] = (-3.5,2,-3.5)
|
||||
points['powerup_spawn2'] = (-3.4,2,3.5)
|
||||
points['powerup_spawn3'] = (3.5,2,-3.5)
|
||||
points['powerup_spawn4'] = (3.5,2,3.5)
|
||||
|
||||
class Dark(ba.Map):
|
||||
from new_maps import darkness_defs as defs
|
||||
name = 'Dark world'
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_play_types(cls) -> List[str]:
|
||||
"""Return valid play types for this map."""
|
||||
return ['melee','king_of_the_hill','keep_away','team_flag']
|
||||
|
||||
@classmethod
|
||||
def get_preview_texture_name(cls) -> str:
|
||||
return 'bg'
|
||||
|
||||
@classmethod
|
||||
def on_preload(cls) -> Any:
|
||||
data: Dict[str, Any] = {
|
||||
'model': ba.getmodel('footballStadium'),
|
||||
'collide_model': ba.getcollidemodel('footballStadiumCollide'),
|
||||
'tex': ba.gettexture('bg'),
|
||||
}
|
||||
return data
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
shared = SharedObjects.get()
|
||||
self.node = ba.newnode('terrain', delegate=self,
|
||||
attrs={
|
||||
'model':self.preloaddata['model'],
|
||||
'collide_model':self.preloaddata['collide_model'],
|
||||
'color_texture':self.preloaddata['tex'],
|
||||
'materials':[shared.footing_material]})
|
||||
|
||||
self.zone = ba.newnode('locator',
|
||||
attrs={'shape':'circleOutline','position':(0,0,0),
|
||||
'color':(1,1,1),'opacity':1,'draw_beauty':True,'additive':False,'size':[11]})
|
||||
|
||||
gnode = ba.getactivity().globalsnode
|
||||
gnode.tint = (0.8,0.8,1)
|
||||
gnode.ambient_color = (1.15,1.25,1.6)
|
||||
gnode.vignette_outer = (0.66,0.67,0.73)
|
||||
gnode.vignette_inner = (0.93,0.93,0.95)
|
||||
|
||||
|
||||
|
||||
class SuperTntMap(ba.Map):
|
||||
"""A giant mine!"""
|
||||
|
||||
from new_maps import powerups_defs as defs
|
||||
|
||||
name = 'Super TNT'
|
||||
|
||||
@classmethod
|
||||
def get_play_types(cls) -> List[str]:
|
||||
"""Return valid play types for this map."""
|
||||
return ['melee']
|
||||
|
||||
@classmethod
|
||||
def get_preview_texture_name(cls) -> str:
|
||||
return 'tnt'
|
||||
|
||||
@classmethod
|
||||
def on_preload(cls) -> Any:
|
||||
data: Dict[str, Any] = {
|
||||
'model': ba.getmodel('powerupSimple'),
|
||||
'tex': ba.gettexture('tnt'),
|
||||
'bgtex': ba.gettexture('menuBG'),
|
||||
'bgmodel': ba.getmodel('thePadBG'),
|
||||
}
|
||||
return data
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
shared = SharedObjects.get()
|
||||
self.node = ba.newnode('prop',
|
||||
delegate=self,
|
||||
attrs={'position':(0,-3.2,0),
|
||||
'velocity':(0,0,0),
|
||||
'model':self.preloaddata['model'],
|
||||
'model_scale':18,
|
||||
'body_scale':15,
|
||||
'density':999999999999999999999,
|
||||
'damping':999999999999999999999,
|
||||
'gravity_scale':0,
|
||||
'body':'crate',
|
||||
'color_texture':self.preloaddata['tex'],
|
||||
'materials':[shared.footing_material]})
|
||||
|
||||
|
||||
self.background = ba.newnode('terrain',
|
||||
attrs={
|
||||
'model': self.preloaddata['bgmodel'],
|
||||
'lighting': False,
|
||||
'background': True,
|
||||
'color_texture': self.preloaddata['bgtex']
|
||||
})
|
||||
|
||||
gnode = ba.getactivity().globalsnode
|
||||
gnode.tint = (1.0, 1.0, 1.0)
|
||||
gnode.ambient_color = (1.1, 1.1, 1.0)
|
||||
gnode.vignette_outer = (0.7, 0.65, 0.75)
|
||||
gnode.vignette_inner = (0.95, 0.95, 0.93)
|
||||
|
||||
|
||||
|
||||
class GreenScreenMap(ba.Map):
|
||||
"""A giant mine!"""
|
||||
|
||||
from bastd.mapdata import doom_shroom as defs
|
||||
|
||||
name = 'Green Screen'
|
||||
|
||||
@classmethod
|
||||
def get_play_types(cls) -> List[str]:
|
||||
"""Return valid play types for this map."""
|
||||
return ['melee','keep_away','team_flag']
|
||||
|
||||
@classmethod
|
||||
def get_preview_texture_name(cls) -> str:
|
||||
return 'eggTex2'
|
||||
|
||||
@classmethod
|
||||
def on_preload(cls) -> Any:
|
||||
data: Dict[str, Any] = {
|
||||
'model': ba.getmodel('doomShroomLevel'),
|
||||
'collide_model': ba.getcollidemodel('doomShroomLevelCollide'),
|
||||
'tex': ba.gettexture('white'),
|
||||
'bgtex': ba.gettexture('doomShroomBGColor'),
|
||||
'bgmodel': ba.getmodel('doomShroomBG'),
|
||||
'stem_model': ba.getmodel('doomShroomStem'),
|
||||
'collide_bg': ba.getcollidemodel('doomShroomStemCollide'),
|
||||
}
|
||||
return data
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
shared = SharedObjects.get()
|
||||
self.node = ba.newnode(
|
||||
'terrain',
|
||||
delegate=self,
|
||||
attrs={
|
||||
'collide_model': self.preloaddata['collide_model'],
|
||||
'model': self.preloaddata['model'],
|
||||
'color':(0,1,0),
|
||||
'color_texture': self.preloaddata['tex'],
|
||||
'materials': [shared.footing_material]
|
||||
})
|
||||
self.background = ba.newnode(
|
||||
'terrain',
|
||||
attrs={
|
||||
'model': self.preloaddata['bgmodel'],
|
||||
'lighting': False,
|
||||
'color':(0,1,0),
|
||||
'background': True,
|
||||
'color_texture': self.preloaddata['tex']
|
||||
})
|
||||
self.stem = ba.newnode('terrain',
|
||||
attrs={
|
||||
'model': self.preloaddata['stem_model'],
|
||||
'lighting': False,
|
||||
'color':(0,1,0),
|
||||
'color_texture': self.preloaddata['tex']
|
||||
})
|
||||
self.bg_collide = ba.newnode(
|
||||
'terrain',
|
||||
attrs={
|
||||
'collide_model': self.preloaddata['collide_bg'],
|
||||
'materials': [shared.footing_material, shared.death_material]
|
||||
})
|
||||
|
||||
gnode = ba.getactivity().globalsnode
|
||||
gnode.tint = (0.82, 1.10, 1.15)
|
||||
gnode.ambient_color = (0.9, 1.3, 1.1)
|
||||
gnode.shadow_ortho = False
|
||||
gnode.vignette_outer = (0.76, 0.76, 0.76)
|
||||
gnode.vignette_inner = (0.95, 0.95, 0.99)
|
||||
|
||||
##### List containing the maps to be registered #####
|
||||
MAPS = [MegaMine,PowerupMap,Dark,SuperTntMap,GreenScreenMap]
|
||||
|
||||
def register_maps():
|
||||
for new_map in MAPS:
|
||||
ba._map.register_map(new_map)
|
||||
|
||||
# ba_meta export plugin
|
||||
class MoreMaps(ba.Plugin):
|
||||
def __init__(self):
|
||||
if _ba.env().get("build_number", 0) >= 20258:
|
||||
register_maps()
|
||||
else:
|
||||
print("new_maps.py only runs with BombSquad versions higher than 1.5.29.")
|
||||
BIN
dist/ba_root/mods/maps/soccerStadiumPro.so
vendored
BIN
dist/ba_root/mods/maps/soccerStadiumPro.so
vendored
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue