Squashed commit for update 1.3.7
21
.gitea/ISSUE_TEMPLATE/choreo.yaml
Normal file
@ -0,0 +1,21 @@
|
||||
name: Choreography Problem
|
||||
about: A template for discussing choreography problems
|
||||
title: "[Chapter XX]: "
|
||||
labels:
|
||||
- bug
|
||||
- "help wanted"
|
||||
body:
|
||||
- type: input
|
||||
id: where
|
||||
attributes:
|
||||
label: On what line did this bug occour?
|
||||
placeholder: "I \"This shit fucks and sucks!\""
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: what
|
||||
attributes:
|
||||
label: "What happened?"
|
||||
placeholder: "The expression \"Inco Sad\" was used at a time when it shouldn't have been used."
|
||||
validations:
|
||||
required: true
|
@ -30,14 +30,14 @@ steps:
|
||||
- event: cron
|
||||
|
||||
build:
|
||||
image: openjdk:8
|
||||
image: openjdk:21-jdk-bookworm
|
||||
commands:
|
||||
- apt update
|
||||
- apt install libgl1 -y
|
||||
- apt install libgl1 patch -y
|
||||
- sed -i -e "s/VERSION/${RenpyVersion}/g" game/options.rpy #Change the renpy version to the woodpecker reuqested one.
|
||||
#Get Renkit
|
||||
- wget -qO- "https://github.com/kobaltcore/renkit/releases/download/v${RenkitVersion}/renkit-linux-amd64.tar.gz" | tar xz --directory=/tmp/
|
||||
- /tmp/renconstruct build -i "." -c "renconstruct.toml" -o dist/
|
||||
- wget -qO- "https://github.com/kobaltcore/renkit/releases/download/v${RenkitVersion}/renkit-x86_64-unknown-linux-gnu.tar.xz" | tar -Jax --directory=/tmp/
|
||||
- /tmp/renkit-x86_64-unknown-linux-gnu/renconstruct build "." dist/
|
||||
- mkdir "dist/android"
|
||||
- mv dist/*.apk "dist/android"
|
||||
- cd /tmp/
|
||||
@ -83,6 +83,6 @@ steps:
|
||||
|
||||
matrix:
|
||||
RenpyVersion:
|
||||
- "8.1.3"
|
||||
- "8.2.1"
|
||||
RenkitVersion:
|
||||
- "3.3.1"
|
||||
- "4.1.0"
|
||||
|
768
LICENSE
@ -1,385 +1,385 @@
|
||||
The "GNU AFFERO GENERAL PUBLIC LICENSE" as wrote out in the "GNU AFFERO GENERAL PUBLIC LICENSE V3.txt" file applies to all computer software files, source or object code, originating from Cavemanon or its contributors.
|
||||
The "Cavemanon Affero GPL v3.0 Video Game Store Front Exception v2.0" as wrote out in the "GPL-Exception.txt" file applies to all copyrightable assets originating from Cavemanon or its contributors that come with this software.
|
||||
The "Attribution-ShareAlike 4.0 International" as wrote out in the "CC-BY-SA-4.0.txt" file applies to all copyrightable audio and image assets originating from Cavemanon or its contributors that is not a computer software file, with the exception of the following assets, which use "Attribution 4.0 International" as wrote out in the "CC-BY-4.0.txt":
|
||||
-game\images\animations\notagoodtime\anim_notagoodtime_f1.png
|
||||
-game\images\animations\notagoodtime\anim_notagoodtime_f2.png
|
||||
-game\images\animations\toilet\anim_toilet.webm
|
||||
-game\images\animations\toilet\anim_toilet_mask.webm
|
||||
-game\images\credits\spr_creditsimage_notagoodtime.png
|
||||
-game\images\credits\spr_creditsimage_miahoe.png
|
||||
|
||||
Non-Cavemanon sourced items with attribution clauses
|
||||
====================================================
|
||||
|
||||
--- SOUNDS ---
|
||||
|
||||
"S Dissapproval - Alt.wav" by Processaurus
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/Processaurus/sounds/440088/
|
||||
|
||||
"Rolling Creak.wav" by lukaspearse
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/lukaspearse/sounds/149736/
|
||||
|
||||
"Interior Wind Noise_Zoom H6.wav" by omnisounddesign
|
||||
LICENSED UNDER ATTRIBUTION 3.0 (CC BY 3.0)
|
||||
https://freesound.org/people/omnisounddesign/sounds/335703/
|
||||
|
||||
"Take off - Small pop.wav" by Quistard
|
||||
LICENSED UNDER ATTRIBUTION 3.0 (CC BY 3.0)
|
||||
https://freesound.org/people/Quistard/sounds/237753/
|
||||
|
||||
"Jet_whoosh.wav" by Benboncan
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/Benboncan/sounds/167563/
|
||||
|
||||
"Dodgeball_Bounce1.wav" by burnsie289
|
||||
LICENSED UNDER ATTRIBUTION 3.0 (CC BY 3.0)
|
||||
https://freesound.org/people/burnsie289/sounds/152414/
|
||||
|
||||
"Cracking knuckles.flac" by CGEffex
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/CGEffex/sounds/93981/
|
||||
|
||||
"MassiveBlast.wav" by daveincamas
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/daveincamas/sounds/58507/
|
||||
|
||||
"Water Swirl, Small, 17.wav" by InspectorJ
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/InspectorJ/sounds/398708/
|
||||
|
||||
"Splash, Jumping, A" by InspectorJ
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/InspectorJ/sounds/352101/
|
||||
|
||||
"etl Window 24-96.wav" by cmusounddesign
|
||||
LICENSED UNDER ATTRIBUTION 3.0 (CC BY 3.0)
|
||||
https://freesound.org/people/cmusounddesign/sounds/95893/
|
||||
|
||||
"elevator 3.wav" by Trautwein
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/Trautwein/sounds/262574/
|
||||
|
||||
"taking the elevator" by Tomlija
|
||||
LICENSED UNDER ATTRIBUTION 3.0 (CC BY 3.0)
|
||||
https://freesound.org/people/Tomlija/sounds/202985/
|
||||
|
||||
"Snapping, Wodden Fence, L.wav" by InspectorJ
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/InspectorJ/sounds/352196/
|
||||
|
||||
"Elastic Band on Tarpaulin" by RICHERlandTV
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/RICHERlandTV/sounds/592262/
|
||||
|
||||
"Whip Crack 01.wav" by CGEffex
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/CGEffex/sounds/93100/
|
||||
|
||||
"Snow Ball Throw And Splat" by Mike Koenig
|
||||
LICENSED UNDER ATTRIBUTION 3.0 (CC BY 3.0)
|
||||
https://soundbible.com/632-Snow-Ball-Throw-And-Splat.html
|
||||
|
||||
"Power up yells" by AmeAngelofSin
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/AmeAngelofSin/sounds/382010/
|
||||
|
||||
"female dying scream" by AmeAngelofSin
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/AmeAngelofSin/sounds/394610/
|
||||
|
||||
"dying female" by AmeAngelofSin
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/AmeAngelofSin/sounds/345049/
|
||||
|
||||
"Female battle cries/grunts" by AmeAngelofSin
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/AmeAngelofSin/sounds/264982/
|
||||
|
||||
"ANGRY DOG BARK SNARL flat.wav" by AmeAngelofSin
|
||||
LICENSED UNDER ATTRIBUTION 3.0 (CC BY 3.0)
|
||||
https://freesound.org/people/deleted_user_3424813/sounds/260776/
|
||||
|
||||
"WIT8 - pain" by phantastonia
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/phantastonia/sounds/615023/
|
||||
|
||||
"Door open and close, close" by Moulaythami
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/Moulaythami/sounds/555095/
|
||||
|
||||
"mitchellsounds - EXT_spring_light_wind_mourningdove_MS.wav"
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/mitchellsounds/sounds/517941/
|
||||
|
||||
"20170618_city.garden.fountain.wav"
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/dobroide/sounds/396277/
|
||||
|
||||
--- MUSIC ---
|
||||
|
||||
mus_angry.ogg
|
||||
URL: https://freemusicarchive.org/music/Loyalty_Freak_Music/HYPER_METAL_/Loyalty_Freak_Music_-_HYPER_METAL__-_06_SUPER_METAL/
|
||||
author: Loyalty Freak Music
|
||||
album: HYPER METAL !
|
||||
songname: SUPER METAL
|
||||
license: CC0
|
||||
|
||||
mus_arcade1.ogg
|
||||
URL: https://sampleswap.org/mp3/song.php?id=1185
|
||||
author: benzoul
|
||||
songname: lovepartyinjapan
|
||||
license: CC-BY
|
||||
|
||||
mus_arcade2.ogg
|
||||
URL: https://sampleswap.org/mp3/song.php?id=413
|
||||
author: emanon
|
||||
songname: 21seiki Techno Shonen
|
||||
license: CC-BY
|
||||
|
||||
mus_awkward.ogg
|
||||
URL: https://freemusicarchive.org/music/Soft_and_Furious/The_Merfolk_I_Should_Turn_To_Be/Soft_and_Furious_-_The_Merfolk_I_Should_Turn_To_Be_-_08_Hyper_Staying/
|
||||
author: Soft and Furious
|
||||
album: The Merfolk I Should Turn To Be
|
||||
songname: Hyper Staying
|
||||
license: CC0
|
||||
|
||||
mus_ben.ogg
|
||||
URL: https://freemusicarchive.org/music/koi-discovery/post-morphose/icar-fellmp3/
|
||||
author: Koi-discovery
|
||||
album: Post-Morphose
|
||||
songname: Icar_Fell.mp3
|
||||
license: CC0
|
||||
|
||||
mus_calm2.ogg
|
||||
URL: https://freemusicarchive.org/music/Komiku/Its_time_for_adventure__vol_2/Komiku_-_Its_time_for_adventure_vol_2_-_08_Dreaming_of_you/
|
||||
author: Komiku
|
||||
album: It's time for adventure ! vol 2
|
||||
songname: Dreaming of you
|
||||
license: CC0
|
||||
|
||||
mus_calm.ogg
|
||||
URL: https://freemusicarchive.org/music/Soft_and_Furious/The_Merfolk_I_Should_Turn_To_Be/Soft_and_Furious_-_The_Merfolk_I_Should_Turn_To_Be_-_02_Youre_no_good_but_I_love_you/
|
||||
author: Soft and Furious
|
||||
album: The Merfolk I Should Turn To Be
|
||||
songname: You're no good but I love you
|
||||
license: CC0
|
||||
|
||||
mus_casual.ogg
|
||||
URL: https://freemusicarchive.org/music/holiznacc0/left-overs/even-after-all-these-years/
|
||||
author: HoliznaCC0
|
||||
album: Left Overs
|
||||
songname: Even After All These Years
|
||||
license: CC0
|
||||
|
||||
mus_chill1.ogg
|
||||
URL: https://freemusicarchive.org/music/Loyalty_Freak_Music/INSTRUMENTAL_RB_BEATS_TO_SING_OR_RAP_ON/Loyalty_Freak_Music_-_INSTRUMENTAL_RB_BEATS_TO_SING_OR_RAP_ON_-_08_I_care
|
||||
author: Loyalty Freak Music
|
||||
album: INSTRUMENTAL R&B BEATS TO SING OR RAP ON
|
||||
songname: I care
|
||||
license: CC0
|
||||
|
||||
mus_chill2.ogg
|
||||
URL: https://freemusicarchive.org/music/holiznacc0/busted-guitar-jazz/4-jazz/
|
||||
author: HoliznaCC0
|
||||
album: Busted Guitar (JAZZ)
|
||||
songname: 4 (jazz)
|
||||
license: CC0
|
||||
|
||||
mus_chill3.ogg
|
||||
URL: https://freemusicarchive.org/music/holiznacc0/lo-fi-and-chill/everything-you-ever-dreamed/
|
||||
author: HoliznaCC0
|
||||
album: Lo-fi And Chill
|
||||
songname: Everything You Ever Dreamed.
|
||||
license: CC0
|
||||
|
||||
mus_chill_thinking.ogg
|
||||
URL: https://freemusicarchive.org/music/holiznacc0/sad-beats/chills/
|
||||
author: HoliznaCC0
|
||||
album: Sad Beats
|
||||
songname: Chills
|
||||
license: CC0
|
||||
|
||||
mus_damien.ogg
|
||||
URL: https://freemusicarchive.org/music/holiznacc0/rock-montage/americana-1/
|
||||
author: HoliznaCC0
|
||||
album: Rock Montage
|
||||
songname: Americana 1
|
||||
license: CC0
|
||||
|
||||
mus_general.ogg
|
||||
URL: https://freemusicarchive.org/music/wax-lyricist/the-wax-lyricist/high-on-loungin/
|
||||
author: Wax Lyricist
|
||||
album: The Wax Lyricist
|
||||
songname: High on Loungin'
|
||||
license: CC0
|
||||
|
||||
mus_happy2.ogg
|
||||
URL: https://freemusicarchive.org/music/holiznacc0/power-pop/a-small-town-on-pluto-1/
|
||||
author: HoliznaCC0
|
||||
album: Power Pop!
|
||||
songname: A Small Town On Pluto
|
||||
license: CC0
|
||||
|
||||
mus_iadakan.ogg
|
||||
URL: https://freemusicarchive.org/music/holiznacc0/left-overs/space-3/
|
||||
author: HoliznaCC0
|
||||
album: Left Overs
|
||||
songname: Space!
|
||||
license: CC0
|
||||
|
||||
mus_inco.ogg
|
||||
URL: https://freemusicarchive.org/music/koi-discovery/cyborg-breakdown/an-ocytocin-problemmp3/
|
||||
author: Koi-discovery
|
||||
album: Cyborg Breakdown
|
||||
songname: An_Ocytocin_Problem.mp3
|
||||
license: CC0
|
||||
|
||||
mus_introspective3
|
||||
URL: https://freemusicarchive.org/music/Monplaisir/Space_Porn/Monplaisir_-_Space_Porn_-_04_Protect/
|
||||
author: Monplaisir
|
||||
album: Space Porn
|
||||
songname: Protect
|
||||
license: CC0
|
||||
|
||||
mus_melancholy2.ogg
|
||||
URL: https://freemusicarchive.org/music/Monplaisir/Space_Porn/Monplaisir_-_Space_Porn_-_08_Stargazer/
|
||||
author: Monplaisir
|
||||
album: Space Porn
|
||||
songname: Stargazer
|
||||
license: CC0
|
||||
|
||||
mus_melancholy_introspective.ogg
|
||||
URL: https://freemusicarchive.org/music/Monplaisir/PIGEONS_ARE_THE_BEST/Monplaisir_-_PIGEONS_ARE_THE_BEST_-_05_Lightbull/
|
||||
author: Monplaisir
|
||||
album: PIGEONS ARE THE BEST
|
||||
songname: Lightbull
|
||||
license: CC0
|
||||
|
||||
mus_melancholy.ogg
|
||||
URL: https://freemusicarchive.org/music/Loyalty_Freak_Music/TO_CHILL_AND_STAY_AWAKE/Loyalty_Freak_Music_-_TO_CHILL_AND_STAY_AWAKE_-_06_People_are_spinning/
|
||||
author: Loyalty Freak Music
|
||||
album: TO CHILL AND STAY AWAKE
|
||||
songname: People are spinning
|
||||
license: CC0
|
||||
|
||||
mus_melancholy_olivia.ogg
|
||||
URL: https://freemusicarchive.org/music/Monplaisir/Pretty_and_Invisible/Monplaisir_-_Pretty_and_Invisible_-_02_Far_and_High/
|
||||
author: Monplaisir
|
||||
album: Pretty and Invisible
|
||||
songname: Far and High
|
||||
license: CC0
|
||||
|
||||
mus_mia1.ogg
|
||||
URL: https://freemusicarchive.org/music/holiznacc0/rock-montage/punk/
|
||||
author: HoliznaCC0
|
||||
album: Rock Montage
|
||||
songname: Punk
|
||||
license: CC0
|
||||
|
||||
mus_mia2.ogg
|
||||
URL: https://freemusicarchive.org/music/holiznacc0/rock-montage/grunge/
|
||||
author: HoliznaCC0
|
||||
album: Rock Montage
|
||||
songname: Grunge
|
||||
license: CC0
|
||||
mus_misc.ogg
|
||||
URL: https://freemusicarchive.org/music/holiznacc0/kick-it-laid-back-hiphop/unwind/
|
||||
author: HoliznaCC0
|
||||
album: Kick It (laid back HipHop)
|
||||
songname: Unwind
|
||||
license: CC0
|
||||
|
||||
mus_pissed.ogg
|
||||
URL: https://freemusicarchive.org/music/Monplaisir/Pretty_and_Invisible/Monplaisir_-_Pretty_and_Invisible_-_06_Talentuous_and_Shy/
|
||||
author: Monplaisir
|
||||
album: Pretty and Invisible
|
||||
songname: Talentuous and Shy
|
||||
license: CC0
|
||||
|
||||
mus_rock.ogg
|
||||
URL: https://freesound.org/people/Jibey-/sounds/572947/
|
||||
author: Jibey-
|
||||
songname: Rock music.wav
|
||||
license: CC-BY
|
||||
|
||||
mus_slow.ogg
|
||||
URL: https://freemusicarchive.org/music/holiznacc0/lo-fi-and-chill/ramenmp3/
|
||||
author: Ramen.mp3
|
||||
album: Lo-fi And Chill
|
||||
songname: ramenmp3
|
||||
license: CC0
|
||||
|
||||
mus_thoughts1.ogg
|
||||
URL: https://freemusicarchive.org/music/Monplaisir/PIGEONS_ARE_THE_BEST/Monplaisir_-_PIGEONS_ARE_THE_BEST_-_01_Jump__Oh_Hi_Mark/
|
||||
author: Monplaisir
|
||||
album: PIGEONS ARE THE BEST
|
||||
songname: Jump ! Oh Hi Mark
|
||||
license: CC0
|
||||
|
||||
mus_thoughts2
|
||||
URL: https://freemusicarchive.org/music/Monplaisir/Pretty_and_Invisible/Monplaisir_-_Pretty_and_Invisible_-_01_Loved_and_Respected/
|
||||
author: Monplaisir
|
||||
album: Pretty and Invisible
|
||||
songname: Loved and Respected
|
||||
license: CC0
|
||||
|
||||
mus_titlescreen.ogg
|
||||
URL: https://freemusicarchive.org/music/holiznacc0/be-happy-with-who-you-are/finding-yourself/
|
||||
author: HoliznaCC0
|
||||
album: Be Happy With Who You Are
|
||||
songname: Finding Yourself
|
||||
license: CC0
|
||||
|
||||
mus_trouble.ogg
|
||||
URL: https://freemusicarchive.org/music/Loyalty_Freak_Music/TO_CHILL_AND_STAY_AWAKE/Loyalty_Freak_Music_-_TO_CHILL_AND_STAY_AWAKE_-_05_Traveling_in_your_mind/
|
||||
author: Loyalty Freak Music
|
||||
album: TO CHILL AND STAY AWAKE
|
||||
songname: Traveling in your mind
|
||||
license: CC0
|
||||
|
||||
mus_upbeat.ogg
|
||||
URL: https://freemusicarchive.org/music/holiznacc0/lo-fi-and-chill/busted-jazz
|
||||
author: HoliznaCC0
|
||||
album: Lo-fi And Chill
|
||||
songname: Busted Jazz
|
||||
license: CC0
|
||||
|
||||
--- GRAPHICS ---
|
||||
|
||||
"The Resort at Pelican Hill" by Ansel Adams
|
||||
LICENSED UNDER ATTRIBUTION 2.0 (CC BY 2.0)
|
||||
https://www.flickr.com/photos/prayitnophotography/8468342892/
|
||||
|
||||
"Inside 360 Restaurant" by Larry Koester
|
||||
LICENSED UNDER ATTRIBUTION 2.0 (CC BY 2.0)
|
||||
https://www.flickr.com/photos/larrywkoester/22976555815/
|
||||
|
||||
"Banquet set up - Novotel Century Hong Kong Hotel" by RichardToHKG
|
||||
LICENSED UNDER ATTRIBUTION 3.0 UNPORTED (CC BY 3.0)
|
||||
https://commons.wikimedia.org/wiki/File:Banquet_set_up_-_Novotel_Century_Hong_Kong_Hotel.jpg
|
||||
|
||||
"Seattle from the Space Needle" by Peter Kaminski
|
||||
LICENSED UNDER ATTRIBUTION 2.0 (CC BY 2.0)
|
||||
https://www.flickr.com/photos/peterkaminski/5444827/
|
||||
|
||||
"Bar" by fr1da
|
||||
LICENSED UNDER ATTRIBUTION 2.0 (CC BY 2.0)
|
||||
https://www.flickr.com/photos/denero188_36624278/2090013005
|
||||
|
||||
"Pleading face" and "Crocodile emoji" by Twitter/X
|
||||
Copyright 2020 Twitter, Inc and other contributors
|
||||
Graphics licensed under CC-BY 4.0: https://creativecommons.org/licenses/by/4.0/
|
||||
|
||||
"Swing" by Julia Koefender
|
||||
LICENSED UNDER ATTRIBUTION 2.0 (CC BY 2.0)
|
||||
https://www.flickr.com/photos/juliakoefender/7128081493/
|
||||
|
||||
"Kitchen in our Hollywood Hills Hidden Gem apartment - Los Angeles, California, USA" by Glen Bowman
|
||||
LICENSED UNDER ATTRIBUTION 2.0 (CC BY 2.0)
|
||||
https://www.flickr.com/photos/glenbowman/18180131123/
|
||||
|
||||
"Sunset with yachts near Phuket island, Thailand XOKA2050s" by Phuket@photographer.net
|
||||
LICENSED UNDER ATTRIBUTION 2.0 (CC BY 2.0)
|
||||
The "GNU AFFERO GENERAL PUBLIC LICENSE" as wrote out in the "GNU AFFERO GENERAL PUBLIC LICENSE V3.txt" file applies to all computer software files, source or object code, originating from Cavemanon or its contributors.
|
||||
The "Cavemanon Affero GPL v3.0 Video Game Store Front Exception v2.0" as wrote out in the "GPL-Exception.txt" file applies to all copyrightable assets originating from Cavemanon or its contributors that come with this software.
|
||||
The "Attribution-ShareAlike 4.0 International" as wrote out in the "CC-BY-SA-4.0.txt" file applies to all copyrightable audio and image assets originating from Cavemanon or its contributors that is not a computer software file, with the exception of the following assets, which use "Attribution 4.0 International" as wrote out in the "CC-BY-4.0.txt":
|
||||
-game\images\animations\notagoodtime\anim_notagoodtime_f1.png
|
||||
-game\images\animations\notagoodtime\anim_notagoodtime_f2.png
|
||||
-game\images\animations\toilet\anim_toilet.webm
|
||||
-game\images\animations\toilet\anim_toilet_mask.webm
|
||||
-game\images\credits\spr_creditsimage_notagoodtime.png
|
||||
-game\images\credits\spr_creditsimage_miahoe.png
|
||||
|
||||
Non-Cavemanon sourced items with attribution clauses
|
||||
====================================================
|
||||
|
||||
--- SOUNDS ---
|
||||
|
||||
"S Dissapproval - Alt.wav" by Processaurus
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/Processaurus/sounds/440088/
|
||||
|
||||
"Rolling Creak.wav" by lukaspearse
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/lukaspearse/sounds/149736/
|
||||
|
||||
"Interior Wind Noise_Zoom H6.wav" by omnisounddesign
|
||||
LICENSED UNDER ATTRIBUTION 3.0 (CC BY 3.0)
|
||||
https://freesound.org/people/omnisounddesign/sounds/335703/
|
||||
|
||||
"Take off - Small pop.wav" by Quistard
|
||||
LICENSED UNDER ATTRIBUTION 3.0 (CC BY 3.0)
|
||||
https://freesound.org/people/Quistard/sounds/237753/
|
||||
|
||||
"Jet_whoosh.wav" by Benboncan
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/Benboncan/sounds/167563/
|
||||
|
||||
"Dodgeball_Bounce1.wav" by burnsie289
|
||||
LICENSED UNDER ATTRIBUTION 3.0 (CC BY 3.0)
|
||||
https://freesound.org/people/burnsie289/sounds/152414/
|
||||
|
||||
"Cracking knuckles.flac" by CGEffex
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/CGEffex/sounds/93981/
|
||||
|
||||
"MassiveBlast.wav" by daveincamas
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/daveincamas/sounds/58507/
|
||||
|
||||
"Water Swirl, Small, 17.wav" by InspectorJ
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/InspectorJ/sounds/398708/
|
||||
|
||||
"Splash, Jumping, A" by InspectorJ
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/InspectorJ/sounds/352101/
|
||||
|
||||
"etl Window 24-96.wav" by cmusounddesign
|
||||
LICENSED UNDER ATTRIBUTION 3.0 (CC BY 3.0)
|
||||
https://freesound.org/people/cmusounddesign/sounds/95893/
|
||||
|
||||
"elevator 3.wav" by Trautwein
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/Trautwein/sounds/262574/
|
||||
|
||||
"taking the elevator" by Tomlija
|
||||
LICENSED UNDER ATTRIBUTION 3.0 (CC BY 3.0)
|
||||
https://freesound.org/people/Tomlija/sounds/202985/
|
||||
|
||||
"Snapping, Wodden Fence, L.wav" by InspectorJ
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/InspectorJ/sounds/352196/
|
||||
|
||||
"Elastic Band on Tarpaulin" by RICHERlandTV
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/RICHERlandTV/sounds/592262/
|
||||
|
||||
"Whip Crack 01.wav" by CGEffex
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/CGEffex/sounds/93100/
|
||||
|
||||
"Snow Ball Throw And Splat" by Mike Koenig
|
||||
LICENSED UNDER ATTRIBUTION 3.0 (CC BY 3.0)
|
||||
https://soundbible.com/632-Snow-Ball-Throw-And-Splat.html
|
||||
|
||||
"Power up yells" by AmeAngelofSin
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/AmeAngelofSin/sounds/382010/
|
||||
|
||||
"female dying scream" by AmeAngelofSin
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/AmeAngelofSin/sounds/394610/
|
||||
|
||||
"dying female" by AmeAngelofSin
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/AmeAngelofSin/sounds/345049/
|
||||
|
||||
"Female battle cries/grunts" by AmeAngelofSin
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/AmeAngelofSin/sounds/264982/
|
||||
|
||||
"ANGRY DOG BARK SNARL flat.wav" by AmeAngelofSin
|
||||
LICENSED UNDER ATTRIBUTION 3.0 (CC BY 3.0)
|
||||
https://freesound.org/people/deleted_user_3424813/sounds/260776/
|
||||
|
||||
"WIT8 - pain" by phantastonia
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/phantastonia/sounds/615023/
|
||||
|
||||
"Door open and close, close" by Moulaythami
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/Moulaythami/sounds/555095/
|
||||
|
||||
"mitchellsounds - EXT_spring_light_wind_mourningdove_MS.wav"
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/mitchellsounds/sounds/517941/
|
||||
|
||||
"20170618_city.garden.fountain.wav"
|
||||
LICENSED UNDER ATTRIBUTION 4.0 (CC BY 4.0)
|
||||
https://freesound.org/people/dobroide/sounds/396277/
|
||||
|
||||
--- MUSIC ---
|
||||
|
||||
mus_angry.ogg
|
||||
URL: https://freemusicarchive.org/music/Loyalty_Freak_Music/HYPER_METAL_/Loyalty_Freak_Music_-_HYPER_METAL__-_06_SUPER_METAL/
|
||||
author: Loyalty Freak Music
|
||||
album: HYPER METAL !
|
||||
songname: SUPER METAL
|
||||
license: CC0
|
||||
|
||||
mus_arcade1.ogg
|
||||
URL: https://sampleswap.org/mp3/song.php?id=1185
|
||||
author: benzoul
|
||||
songname: lovepartyinjapan
|
||||
license: CC-BY
|
||||
|
||||
mus_arcade2.ogg
|
||||
URL: https://sampleswap.org/mp3/song.php?id=413
|
||||
author: emanon
|
||||
songname: 21seiki Techno Shonen
|
||||
license: CC-BY
|
||||
|
||||
mus_awkward.ogg
|
||||
URL: https://freemusicarchive.org/music/Soft_and_Furious/The_Merfolk_I_Should_Turn_To_Be/Soft_and_Furious_-_The_Merfolk_I_Should_Turn_To_Be_-_08_Hyper_Staying/
|
||||
author: Soft and Furious
|
||||
album: The Merfolk I Should Turn To Be
|
||||
songname: Hyper Staying
|
||||
license: CC0
|
||||
|
||||
mus_ben.ogg
|
||||
URL: https://freemusicarchive.org/music/koi-discovery/post-morphose/icar-fellmp3/
|
||||
author: Koi-discovery
|
||||
album: Post-Morphose
|
||||
songname: Icar_Fell.mp3
|
||||
license: CC0
|
||||
|
||||
mus_calm2.ogg
|
||||
URL: https://freemusicarchive.org/music/Komiku/Its_time_for_adventure__vol_2/Komiku_-_Its_time_for_adventure_vol_2_-_08_Dreaming_of_you/
|
||||
author: Komiku
|
||||
album: It's time for adventure ! vol 2
|
||||
songname: Dreaming of you
|
||||
license: CC0
|
||||
|
||||
mus_calm.ogg
|
||||
URL: https://freemusicarchive.org/music/Soft_and_Furious/The_Merfolk_I_Should_Turn_To_Be/Soft_and_Furious_-_The_Merfolk_I_Should_Turn_To_Be_-_02_Youre_no_good_but_I_love_you/
|
||||
author: Soft and Furious
|
||||
album: The Merfolk I Should Turn To Be
|
||||
songname: You're no good but I love you
|
||||
license: CC0
|
||||
|
||||
mus_casual.ogg
|
||||
URL: https://freemusicarchive.org/music/holiznacc0/left-overs/even-after-all-these-years/
|
||||
author: HoliznaCC0
|
||||
album: Left Overs
|
||||
songname: Even After All These Years
|
||||
license: CC0
|
||||
|
||||
mus_chill1.ogg
|
||||
URL: https://freemusicarchive.org/music/Loyalty_Freak_Music/INSTRUMENTAL_RB_BEATS_TO_SING_OR_RAP_ON/Loyalty_Freak_Music_-_INSTRUMENTAL_RB_BEATS_TO_SING_OR_RAP_ON_-_08_I_care
|
||||
author: Loyalty Freak Music
|
||||
album: INSTRUMENTAL R&B BEATS TO SING OR RAP ON
|
||||
songname: I care
|
||||
license: CC0
|
||||
|
||||
mus_chill2.ogg
|
||||
URL: https://freemusicarchive.org/music/holiznacc0/busted-guitar-jazz/4-jazz/
|
||||
author: HoliznaCC0
|
||||
album: Busted Guitar (JAZZ)
|
||||
songname: 4 (jazz)
|
||||
license: CC0
|
||||
|
||||
mus_chill3.ogg
|
||||
URL: https://freemusicarchive.org/music/holiznacc0/lo-fi-and-chill/everything-you-ever-dreamed/
|
||||
author: HoliznaCC0
|
||||
album: Lo-fi And Chill
|
||||
songname: Everything You Ever Dreamed.
|
||||
license: CC0
|
||||
|
||||
mus_chill_thinking.ogg
|
||||
URL: https://freemusicarchive.org/music/holiznacc0/sad-beats/chills/
|
||||
author: HoliznaCC0
|
||||
album: Sad Beats
|
||||
songname: Chills
|
||||
license: CC0
|
||||
|
||||
mus_damien.ogg
|
||||
URL: https://freemusicarchive.org/music/holiznacc0/rock-montage/americana-1/
|
||||
author: HoliznaCC0
|
||||
album: Rock Montage
|
||||
songname: Americana 1
|
||||
license: CC0
|
||||
|
||||
mus_general.ogg
|
||||
URL: https://freemusicarchive.org/music/wax-lyricist/the-wax-lyricist/high-on-loungin/
|
||||
author: Wax Lyricist
|
||||
album: The Wax Lyricist
|
||||
songname: High on Loungin'
|
||||
license: CC0
|
||||
|
||||
mus_happy2.ogg
|
||||
URL: https://freemusicarchive.org/music/holiznacc0/power-pop/a-small-town-on-pluto-1/
|
||||
author: HoliznaCC0
|
||||
album: Power Pop!
|
||||
songname: A Small Town On Pluto
|
||||
license: CC0
|
||||
|
||||
mus_iadakan.ogg
|
||||
URL: https://freemusicarchive.org/music/holiznacc0/left-overs/space-3/
|
||||
author: HoliznaCC0
|
||||
album: Left Overs
|
||||
songname: Space!
|
||||
license: CC0
|
||||
|
||||
mus_inco.ogg
|
||||
URL: https://freemusicarchive.org/music/koi-discovery/cyborg-breakdown/an-ocytocin-problemmp3/
|
||||
author: Koi-discovery
|
||||
album: Cyborg Breakdown
|
||||
songname: An_Ocytocin_Problem.mp3
|
||||
license: CC0
|
||||
|
||||
mus_introspective3
|
||||
URL: https://freemusicarchive.org/music/Monplaisir/Space_Porn/Monplaisir_-_Space_Porn_-_04_Protect/
|
||||
author: Monplaisir
|
||||
album: Space Porn
|
||||
songname: Protect
|
||||
license: CC0
|
||||
|
||||
mus_melancholy2.ogg
|
||||
URL: https://freemusicarchive.org/music/Monplaisir/Space_Porn/Monplaisir_-_Space_Porn_-_08_Stargazer/
|
||||
author: Monplaisir
|
||||
album: Space Porn
|
||||
songname: Stargazer
|
||||
license: CC0
|
||||
|
||||
mus_melancholy_introspective.ogg
|
||||
URL: https://freemusicarchive.org/music/Monplaisir/PIGEONS_ARE_THE_BEST/Monplaisir_-_PIGEONS_ARE_THE_BEST_-_05_Lightbull/
|
||||
author: Monplaisir
|
||||
album: PIGEONS ARE THE BEST
|
||||
songname: Lightbull
|
||||
license: CC0
|
||||
|
||||
mus_melancholy.ogg
|
||||
URL: https://freemusicarchive.org/music/Loyalty_Freak_Music/TO_CHILL_AND_STAY_AWAKE/Loyalty_Freak_Music_-_TO_CHILL_AND_STAY_AWAKE_-_06_People_are_spinning/
|
||||
author: Loyalty Freak Music
|
||||
album: TO CHILL AND STAY AWAKE
|
||||
songname: People are spinning
|
||||
license: CC0
|
||||
|
||||
mus_melancholy_olivia.ogg
|
||||
URL: https://freemusicarchive.org/music/Monplaisir/Pretty_and_Invisible/Monplaisir_-_Pretty_and_Invisible_-_02_Far_and_High/
|
||||
author: Monplaisir
|
||||
album: Pretty and Invisible
|
||||
songname: Far and High
|
||||
license: CC0
|
||||
|
||||
mus_mia1.ogg
|
||||
URL: https://freemusicarchive.org/music/holiznacc0/rock-montage/punk/
|
||||
author: HoliznaCC0
|
||||
album: Rock Montage
|
||||
songname: Punk
|
||||
license: CC0
|
||||
|
||||
mus_mia2.ogg
|
||||
URL: https://freemusicarchive.org/music/holiznacc0/rock-montage/grunge/
|
||||
author: HoliznaCC0
|
||||
album: Rock Montage
|
||||
songname: Grunge
|
||||
license: CC0
|
||||
mus_misc.ogg
|
||||
URL: https://freemusicarchive.org/music/holiznacc0/kick-it-laid-back-hiphop/unwind/
|
||||
author: HoliznaCC0
|
||||
album: Kick It (laid back HipHop)
|
||||
songname: Unwind
|
||||
license: CC0
|
||||
|
||||
mus_pissed.ogg
|
||||
URL: https://freemusicarchive.org/music/Monplaisir/Pretty_and_Invisible/Monplaisir_-_Pretty_and_Invisible_-_06_Talentuous_and_Shy/
|
||||
author: Monplaisir
|
||||
album: Pretty and Invisible
|
||||
songname: Talentuous and Shy
|
||||
license: CC0
|
||||
|
||||
mus_rock.ogg
|
||||
URL: https://freesound.org/people/Jibey-/sounds/572947/
|
||||
author: Jibey-
|
||||
songname: Rock music.wav
|
||||
license: CC-BY
|
||||
|
||||
mus_slow.ogg
|
||||
URL: https://freemusicarchive.org/music/holiznacc0/lo-fi-and-chill/ramenmp3/
|
||||
author: Ramen.mp3
|
||||
album: Lo-fi And Chill
|
||||
songname: ramenmp3
|
||||
license: CC0
|
||||
|
||||
mus_thoughts1.ogg
|
||||
URL: https://freemusicarchive.org/music/Monplaisir/PIGEONS_ARE_THE_BEST/Monplaisir_-_PIGEONS_ARE_THE_BEST_-_01_Jump__Oh_Hi_Mark/
|
||||
author: Monplaisir
|
||||
album: PIGEONS ARE THE BEST
|
||||
songname: Jump ! Oh Hi Mark
|
||||
license: CC0
|
||||
|
||||
mus_thoughts2
|
||||
URL: https://freemusicarchive.org/music/Monplaisir/Pretty_and_Invisible/Monplaisir_-_Pretty_and_Invisible_-_01_Loved_and_Respected/
|
||||
author: Monplaisir
|
||||
album: Pretty and Invisible
|
||||
songname: Loved and Respected
|
||||
license: CC0
|
||||
|
||||
mus_titlescreen.ogg
|
||||
URL: https://freemusicarchive.org/music/holiznacc0/be-happy-with-who-you-are/finding-yourself/
|
||||
author: HoliznaCC0
|
||||
album: Be Happy With Who You Are
|
||||
songname: Finding Yourself
|
||||
license: CC0
|
||||
|
||||
mus_trouble.ogg
|
||||
URL: https://freemusicarchive.org/music/Loyalty_Freak_Music/TO_CHILL_AND_STAY_AWAKE/Loyalty_Freak_Music_-_TO_CHILL_AND_STAY_AWAKE_-_05_Traveling_in_your_mind/
|
||||
author: Loyalty Freak Music
|
||||
album: TO CHILL AND STAY AWAKE
|
||||
songname: Traveling in your mind
|
||||
license: CC0
|
||||
|
||||
mus_upbeat.ogg
|
||||
URL: https://freemusicarchive.org/music/holiznacc0/lo-fi-and-chill/busted-jazz
|
||||
author: HoliznaCC0
|
||||
album: Lo-fi And Chill
|
||||
songname: Busted Jazz
|
||||
license: CC0
|
||||
|
||||
--- GRAPHICS ---
|
||||
|
||||
"The Resort at Pelican Hill" by Ansel Adams
|
||||
LICENSED UNDER ATTRIBUTION 2.0 (CC BY 2.0)
|
||||
https://www.flickr.com/photos/prayitnophotography/8468342892/
|
||||
|
||||
"Inside 360 Restaurant" by Larry Koester
|
||||
LICENSED UNDER ATTRIBUTION 2.0 (CC BY 2.0)
|
||||
https://www.flickr.com/photos/larrywkoester/22976555815/
|
||||
|
||||
"Banquet set up - Novotel Century Hong Kong Hotel" by RichardToHKG
|
||||
LICENSED UNDER ATTRIBUTION 3.0 UNPORTED (CC BY 3.0)
|
||||
https://commons.wikimedia.org/wiki/File:Banquet_set_up_-_Novotel_Century_Hong_Kong_Hotel.jpg
|
||||
|
||||
"Seattle from the Space Needle" by Peter Kaminski
|
||||
LICENSED UNDER ATTRIBUTION 2.0 (CC BY 2.0)
|
||||
https://www.flickr.com/photos/peterkaminski/5444827/
|
||||
|
||||
"Bar" by fr1da
|
||||
LICENSED UNDER ATTRIBUTION 2.0 (CC BY 2.0)
|
||||
https://www.flickr.com/photos/denero188_36624278/2090013005
|
||||
|
||||
"Pleading face" and "Crocodile emoji" by Twitter/X
|
||||
Copyright 2020 Twitter, Inc and other contributors
|
||||
Graphics licensed under CC-BY 4.0: https://creativecommons.org/licenses/by/4.0/
|
||||
|
||||
"Swing" by Julia Koefender
|
||||
LICENSED UNDER ATTRIBUTION 2.0 (CC BY 2.0)
|
||||
https://www.flickr.com/photos/juliakoefender/7128081493/
|
||||
|
||||
"Kitchen in our Hollywood Hills Hidden Gem apartment - Los Angeles, California, USA" by Glen Bowman
|
||||
LICENSED UNDER ATTRIBUTION 2.0 (CC BY 2.0)
|
||||
https://www.flickr.com/photos/glenbowman/18180131123/
|
||||
|
||||
"Sunset with yachts near Phuket island, Thailand XOKA2050s" by Phuket@photographer.net
|
||||
LICENSED UNDER ATTRIBUTION 2.0 (CC BY 2.0)
|
||||
https://www.flickr.com/photos/linvoyage/44910097244/
|
19
README.md
@ -12,14 +12,15 @@ Information regarding how to set up the full game as a Ren'Py project using the
|
||||
|
||||
## Building
|
||||
|
||||
There are two ways to launch this project/make distributions; Through the Ren'Py SDK or RenKit:
|
||||
There are two options for building dependong on your preference:
|
||||
|
||||
- Ren'Py SDK - Good for computerlets/ease of use. Has debugging features and a bit more options. Requires a bit more setup for Android building.
|
||||
- RenKit - Good for automation/terminal users. Dead simple setup, auto downloads all required files for building distributions, including the SDK and Android stuff. Allows CLI interfacing with Ren'Py to launch projects
|
||||
- Ren'Py SDK - For being able to launch the project as a game and/or make personal distributions. Good for computerlets/ease of use. Has debugging features and a bit more options. Requires a bit more setup for Android building. Will not include workshop support by itself.
|
||||
|
||||
- RenKit - For accurate compilation. Good for automation/terminal users. Dead simple setup, auto downloads almost all required files for building distributions, including the SDK and most Android stuff. Allows CLI interfacing with Ren'Py to launch projects. Includes workshop support via the patching functionality.
|
||||
|
||||
### BUILDING WITH THE SDK
|
||||
|
||||
1. [Download the Ren'Py 8.1.3 SDK depending on your system](https://www.renpy.org/release_list.html)
|
||||
1. [Download the Ren'Py 8.2.1 SDK depending on your system](https://www.renpy.org/release_list.html)
|
||||
2. Extract the .zip/.bz2/.dmg or get it through your package manager and run the SDK.
|
||||
3. Clone this repo - Or if you don't use Git, click the '...' button near the topright of this page and click 'Download ZIP' - and place it within the Ren'Py SDK or to a directory of your choosing.
|
||||
4. Launch the SDK and set the projects path to the folder containing your repo. Make sure the project is selected within the projects list.
|
||||
@ -32,9 +33,10 @@ There are two ways to launch this project/make distributions; Through the Ren'Py
|
||||
2. Extract the .zip/.xz or get it through your package manager.
|
||||
3. Clone this repo - Or if you don't use Git, click the '...' button near the topright of this page and click 'Download ZIP' - and place it somewhere you can access.
|
||||
4. Edit the `renconstruct.toml` file in the root of the project files to fit your needs like which distributions you want to build.
|
||||
5. (OPTIONAL) If you want to include building for Android, you'll need to install JDK 21 as renconstruct can't do that automatically. [Read up the Ren'Py documentation for info on how](https://www.renpy.org/doc/html/android.html#step-1-installing-the-dependencies).
|
||||
5. Run `renconstruct.exe` with the following command:
|
||||
```bash
|
||||
renconstruct build -c "<path to demo project files>/renconstruct.toml" "<path to demo project files>" "<path to outputted distributions>"
|
||||
```bash renconstruct build "." dist/
|
||||
renconstruct build "<path to demo project files>" "<path to outputted distributions>" -c "<path to demo project files>/renconstruct.toml"
|
||||
```
|
||||
|
||||
This will start the build process and outputs the game to whatever path you set your distributions to.
|
||||
@ -43,11 +45,10 @@ This will start the build process and outputs the game to whatever path you set
|
||||
|
||||
More information on the build process [can be found here](https://www.renpy.org/doc/html/build.html#building-distributions).
|
||||
|
||||
Information relating to building for Android [can be found here here as well](https://www.renpy.org/doc/html/android.html). Note that for Android, you must use Java SDK 8 until Wani updates to Ren'Py 8.2.0.
|
||||
|
||||
Information relating to building for Android [can be found here here as well](https://www.renpy.org/doc/html/android.html).
|
||||
Information regarding RenKit and it's documentation [can be found on its github page](https://github.com/kobaltcore/renkit)
|
||||
|
||||
The 'woodpecker.yml' file included in the source is for reference in CI/CD and may be useful for some.
|
||||
The 'woodpecker.yml' file included in the source is for reference in CI/CD and may be useful for some. With Woodpecker, versioning can be applied via git tags, and will replace the in-game version variable and the versioning for android with the name of the tag. It's configured for our servers so it's not expected to work right off the bat if you try it.
|
||||
|
||||
## Setting up the full game as a Ren'Py project
|
||||
|
||||
|
29
build_patch/patch.diff
Normal file
@ -0,0 +1,29 @@
|
||||
233a234
|
||||
> import os # @UnresolvedImport
|
||||
236a238,263
|
||||
>
|
||||
> # MODS STUFF
|
||||
> APP_ID = 1895350
|
||||
>
|
||||
> if not renpy.android:
|
||||
> try: # Android will try to run this for some reason and fail
|
||||
> mod_paths = [
|
||||
> f"../../workshop/content/{APP_ID}/",
|
||||
> f"/Users/{os.getlogin()}/Library/Application Support/Steam/steamapps/workshop/content/{APP_ID}/",
|
||||
> os.path.expanduser(f"~/Library/Application Support/Steam/steamapps/workshop/content/{APP_ID}/")
|
||||
> ]
|
||||
> except:
|
||||
> mod_paths = []
|
||||
>
|
||||
> new_paths = []
|
||||
> for path in mod_paths:
|
||||
> try:
|
||||
> if os.path.exists(path):
|
||||
> for name in os.listdir(path):
|
||||
> full_path = os.path.join(path, name)
|
||||
> if os.path.isdir(full_path):
|
||||
> new_paths.append(full_path)
|
||||
> except Exception as e:
|
||||
> renpy.display.log.write(f"Error while adding mod search paths: {e}")
|
||||
>
|
||||
> searchpath += new_paths
|
19
build_patch/patch.py
Normal file
@ -0,0 +1,19 @@
|
||||
class PatchTask:
|
||||
def __init__(self, config, input_dir, output_dir):
|
||||
self.config = config
|
||||
self.input_dir = input_dir
|
||||
self.output_dir = output_dir
|
||||
|
||||
def pre_build(self):
|
||||
import subprocess
|
||||
print("================Initiating patching==================")
|
||||
|
||||
try:
|
||||
subprocess.run(["patch", f"/tmp/cache/{self.config['ver']}/renpy.py", "./build_patch/patch.diff"])
|
||||
except Exception as e:
|
||||
print(e)
|
||||
raise e
|
||||
print("================File Patched==================")
|
||||
|
||||
def post_build(self):
|
||||
pass
|
@ -9,13 +9,17 @@ label chapter_select:
|
||||
camera:
|
||||
resetcamera()
|
||||
yanchor 0.0 xanchor 0.0 rotate None zoom 1.0
|
||||
matrixcolor None
|
||||
|
||||
$ quick_menu = True
|
||||
$ notagoodtime_ui = False
|
||||
$ textbox_offset = 0
|
||||
$ namebox_offset = 0
|
||||
$ _window_alpha = 1.0
|
||||
$ broken_phone = False
|
||||
python:
|
||||
quick_menu = True
|
||||
notagoodtime_ui = False
|
||||
textbox_offset = 0
|
||||
namebox_offset = 0
|
||||
_window_alpha = 1.0
|
||||
broken_phone = False
|
||||
renpy.hide_screen("_phone")
|
||||
renpy.set_return_stack([]) # This prevents timeloop bugs
|
||||
|
||||
call initstats from _call_initstats
|
||||
|
||||
|
@ -5,8 +5,6 @@ init 999 python:
|
||||
#hard code the header & footer
|
||||
#then iterate the list_credits
|
||||
|
||||
|
||||
|
||||
list_credits_start = [
|
||||
_("I Wani Hug That Gator"),
|
||||
_("By Cavemanon"),
|
||||
@ -206,6 +204,35 @@ init 999 python:
|
||||
else:
|
||||
return list_credits[accessor][value]
|
||||
|
||||
SIZE_SNOT_GAMES = 55*3+10
|
||||
SIZE_TITLE = 32*3+10
|
||||
SIZE_ENTRY = 26*3+10
|
||||
SIZE_TL = 26*2+10
|
||||
SIZE_ENDER = 52*3+10
|
||||
|
||||
screen muh_credits():
|
||||
fixed:
|
||||
xalign 0.5
|
||||
vbox:
|
||||
xalign 0.5
|
||||
null width 1 height 16*25
|
||||
text list_credits_start[0] size SIZE_SNOT_GAMES xalign 0.5 yalign 0.5 text_align 0.5 outlines [ (absolute(5), "#000", absolute(0), absolute(0)) ]
|
||||
null width 1 height 16*1
|
||||
text list_credits_start[1] size SIZE_TITLE xalign 0.5 yalign 0.5 text_align 0.5 outlines [ (absolute(5), "#000", absolute(0), absolute(0)) ]
|
||||
null width 1 height 16*18
|
||||
text list_credits_start[2] size SIZE_ENTRY xalign 0.5 yalign 0.5 text_align 0.5 outlines [ (absolute(5), "#000", absolute(0), absolute(0)) ]
|
||||
null width 1 height 16*12
|
||||
|
||||
for key, arr in list_credits.items():
|
||||
text key size SIZE_ENTRY xalign 0.5 yalign 0.5 text_align 0.5 outlines [ (absolute(5), "#000", absolute(0), absolute(0)) ]
|
||||
null width 1 height 16*6
|
||||
vbox:
|
||||
xalign 0.5
|
||||
spacing 17
|
||||
for item in arr:
|
||||
text item size SIZE_ENTRY xalign 0.5 yalign 0.5 text_align 0.5 outlines [ (absolute(5), "#000", absolute(0), absolute(0)) ]
|
||||
null width 1 height 16*3
|
||||
|
||||
transform tf_credits_moveinright(x=0.0, y=0.0, duration=2.0, delay=0.0):
|
||||
subpixel True alpha 0.0
|
||||
pause delay
|
||||
@ -250,7 +277,14 @@ transform tf_credits_slightzoomout_offset(y=0.5, yanchor=0.5):
|
||||
subpixel True
|
||||
linear 7.5 zoom 0.95
|
||||
|
||||
# This can take a string for the text size, intended for renpy's translation generation. The string has to follow this format:
|
||||
# "(number)=(credits text)"
|
||||
# So an example would be:
|
||||
# "100=Directed By"
|
||||
screen endingtext(text="placeholder", text_transform=truecenter, text_align=0.0, text_size=100):
|
||||
python:
|
||||
if isinstance(text_size, str):
|
||||
text_size = int(text_size[0:text_size.find("=")])
|
||||
text text yanchor 0.0 xanchor text_align size text_size text_align text_align outlines [ (absolute(5), "#000", absolute(0), absolute(0)) ] at text_transform
|
||||
|
||||
|
||||
@ -393,12 +427,13 @@ label credits:
|
||||
hide CAVEMANON
|
||||
|
||||
# Display the whole credits list
|
||||
show spr_credits:
|
||||
crop None zoom 1.0 yalign 0.0
|
||||
|
||||
if ending != 3:
|
||||
show spr_credits:
|
||||
crop (0.0, 0.0, 1.0, 17550) zoom 1.0 yalign 0.0 alpha 1.0
|
||||
else:
|
||||
show spr_credits:
|
||||
crop None zoom 1.0 yalign 0.0
|
||||
show black as censor:
|
||||
ypos 16.3
|
||||
xsize 0.9 # We squeeze it so that it doesnt cover the (1) in ending 2
|
||||
show spr_credits_theend:
|
||||
ypos 17.5
|
||||
|
||||
@ -522,7 +557,7 @@ label e4credits_1:
|
||||
parallel:
|
||||
linear 0.5 alpha ALPHA_CONTROLLER
|
||||
|
||||
show screen endingtext(list_credits_titles[0], tf_credits_moveinright(0.15, 0.3, 7))
|
||||
show screen endingtext(list_credits_titles[0], tf_credits_moveinright(0.15, 0.3, 7), text_size=__("100=Directed by"))
|
||||
show screen endingtext(display_credits_names(0, 0), tf_credits_moveinleft(0.85, 0.5, 7), 1.0) as endingtext2
|
||||
|
||||
pause 7.5
|
||||
@ -552,7 +587,7 @@ label e4credits_2:
|
||||
parallel:
|
||||
linear 0.5 alpha ALPHA_CONTROLLER
|
||||
|
||||
show screen endingtext(list_credits_titles[1], tf_credits_moveinright(0.15, 0.1, 7))
|
||||
show screen endingtext(list_credits_titles[1], tf_credits_moveinright(0.15, 0.1, 7), text_size=__("100=Written by"))
|
||||
show screen endingtext(display_credits_names(1), tf_credits_moveinleft(0.85, 0.25, 7), 1.0) as endingtext2
|
||||
|
||||
pause 7.5
|
||||
@ -591,7 +626,7 @@ label e4credits_3:
|
||||
parallel:
|
||||
linear 0.5 alpha ALPHA_CONTROLLER
|
||||
|
||||
show screen endingtext(list_credits_titles[2], tf_credits_moveinright(0.15, 0.6, 7))
|
||||
show screen endingtext(list_credits_titles[2], tf_credits_moveinright(0.15, 0.6, 7), text_size=__("100=Story by"))
|
||||
show screen endingtext(display_credits_names(2), tf_credits_moveinleft(0.85, 0.45, 7), 1.0) as endingtext2
|
||||
|
||||
pause 7.5
|
||||
@ -616,7 +651,7 @@ label e4credits_4:
|
||||
parallel:
|
||||
linear 0.5 alpha ALPHA_CONTROLLER
|
||||
|
||||
show screen endingtext(list_credits_titles[3], tf_credits_moveinright(0.1, 0.6, 7), text_size=85)
|
||||
show screen endingtext(list_credits_titles[3], tf_credits_moveinright(0.1, 0.6, 7), text_size=__("85=Production Coordinator"))
|
||||
show screen endingtext(display_credits_names(3), tf_credits_moveinleft(0.4, 0.75, 7), 1.0) as endingtext2
|
||||
|
||||
pause 7.5
|
||||
@ -660,7 +695,7 @@ label e4credits_5:
|
||||
camera:
|
||||
linear 15 ypos -1.5
|
||||
|
||||
show screen endingtext(list_credits_titles[4], tf_credits_moveinright(0.15, 0.1, 14))
|
||||
show screen endingtext(list_credits_titles[4], tf_credits_moveinright(0.15, 0.1, 14), text_size=__("100=Artwork by"))
|
||||
show screen endingtext(display_credits_names(4, end_index=5), tf_credits_moveinleft(0.85, 0.2, 7), 1.0) as endingtext2
|
||||
|
||||
pause 7
|
||||
@ -737,7 +772,7 @@ label e4credits_6:
|
||||
alpha ALPHA_CONTROLLER
|
||||
shakeend(i=2.0)
|
||||
|
||||
show screen endingtext(list_credits_titles[5], tf_credits_moveinright(0.05, 0.1, 7))
|
||||
show screen endingtext(list_credits_titles[5], tf_credits_moveinright(0.05, 0.1, 7), text_size=__("100=Additional Artwork by"))
|
||||
show screen endingtext(display_credits_names(5), tf_credits_moveinleft(0.55, 0.3, 7), 1.0) as endingtext2
|
||||
|
||||
pause 7.5
|
||||
@ -783,7 +818,7 @@ label e4credits_7:
|
||||
xalign 0.5 yalign 0.5 zoom 1.1
|
||||
linear 8 zoom 1.0
|
||||
|
||||
show screen endingtext(list_credits_titles[6], tf_credits_moveinright(0.125, 0.45, 7))
|
||||
show screen endingtext(list_credits_titles[6], tf_credits_moveinright(0.125, 0.45, 7), text_size=__("100=Stock Photos by"))
|
||||
show screen endingtext(display_credits_names(6), tf_credits_moveinleft(0.85, 0.35, 7), 1.0) as endingtext2
|
||||
|
||||
pause 7.5
|
||||
@ -813,7 +848,7 @@ label e4credits_8:
|
||||
xpos 0.67 ypos 0.66 alpha 0.0
|
||||
linear 0.5 alpha 1
|
||||
|
||||
show screen endingtext(list_credits_titles[7], tf_credits_moveinright(0.1, 0.1, 14))
|
||||
show screen endingtext(list_credits_titles[7], tf_credits_moveinright(0.1, 0.1, 14), text_size=__("100=Animation by"))
|
||||
show screen endingtext(display_credits_names(7, end_index=3), tf_credits_moveinleft(0.9, 0.1, 7), 1.0) as endingtext2
|
||||
|
||||
pause 7
|
||||
@ -852,7 +887,7 @@ label e4credits_9:
|
||||
parallel:
|
||||
linear 0.5 alpha ALPHA_CONTROLLER
|
||||
|
||||
show screen endingtext(list_credits_titles[8], tf_credits_moveinright(0.35, 0.1, 14))
|
||||
show screen endingtext(list_credits_titles[8], tf_credits_moveinright(0.35, 0.1, 14), text_size=__("100=Programming by"))
|
||||
show screen endingtext(display_credits_names(8, end_index=3), tf_credits_moveinleft(0.85, 0.3, 7), 1.0) as endingtext2
|
||||
|
||||
pause 7
|
||||
@ -889,7 +924,7 @@ label e4credits_10:
|
||||
parallel:
|
||||
linear 0.5 alpha ALPHA_CONTROLLER
|
||||
|
||||
show screen endingtext(list_credits_titles[9], tf_credits_moveinright(0.1, 0.2, 7))
|
||||
show screen endingtext(list_credits_titles[9], tf_credits_moveinright(0.1, 0.2, 7), text_size=__("100=Music by"))
|
||||
show screen endingtext(display_credits_names(9), tf_credits_moveinleft(0.5, 0.4, 7), 1.0) as endingtext2
|
||||
|
||||
pause 7.5
|
||||
@ -914,7 +949,7 @@ label e4credits_11:
|
||||
parallel:
|
||||
linear 0.5 alpha ALPHA_CONTROLLER
|
||||
|
||||
show screen endingtext(list_credits_titles[10], tf_credits_moveinright(0.15, 0.15, 14))
|
||||
show screen endingtext(list_credits_titles[10], tf_credits_moveinright(0.15, 0.15, 14), text_size=__("100=Stock Music by"))
|
||||
show screen endingtext(display_credits_names(10, end_index=3), tf_credits_moveinleft(0.85, 0.35, 7), 1.0) as endingtext2
|
||||
|
||||
pause 7
|
||||
@ -956,7 +991,7 @@ label e4credits_12:
|
||||
ypos 0.25 xpos 0.01
|
||||
linear 0.5 alpha ALPHA_CONTROLLER
|
||||
|
||||
show screen endingtext(list_credits_titles[11], tf_credits_moveinright(0.3, 0.2, 7))
|
||||
show screen endingtext(list_credits_titles[11], tf_credits_moveinright(0.3, 0.2, 7), text_size=__("100=Stock Music acquired by"))
|
||||
show screen endingtext(display_credits_names(11), tf_credits_moveinleft(0.9, 0.4, 7), 1.0) as endingtext2
|
||||
|
||||
pause 7.5
|
||||
@ -988,7 +1023,7 @@ label e4credits_13:
|
||||
xpos 0.81 alpha 0.0
|
||||
linear 0.5 alpha ALPHA_CONTROLLER
|
||||
|
||||
show screen endingtext(list_credits_titles[12], tf_credits_moveinright(0.15, 0.2, 7))
|
||||
show screen endingtext(list_credits_titles[12], tf_credits_moveinright(0.15, 0.2, 7), text_size=__("100=Sound by"))
|
||||
show screen endingtext(display_credits_names(12), tf_credits_moveinleft(0.85, 0.4, 7), 1.0) as endingtext2
|
||||
|
||||
pause 7.5
|
||||
@ -1010,7 +1045,7 @@ label e4credits_14:
|
||||
parallel:
|
||||
linear 0.5 alpha ALPHA_CONTROLLER
|
||||
|
||||
show screen endingtext(list_credits_titles[13], tf_credits_moveinright(0.15, 0.1, 14))
|
||||
show screen endingtext(list_credits_titles[13], tf_credits_moveinright(0.15, 0.1, 14), text_size=__("100=Stock Sounds by"))
|
||||
show screen endingtext(display_credits_names(13, end_index=4), tf_credits_moveinleft(0.85, 0.25, 7), 1.0) as endingtext2
|
||||
|
||||
pause 7
|
||||
@ -1039,7 +1074,7 @@ label e4credits_15:
|
||||
ypos 0.0 xpos 0.47 zoom 2.02
|
||||
linear 0.5 alpha ALPHA_CONTROLLER
|
||||
|
||||
show screen endingtext(list_credits_titles[13], tf_credits_moveinright(0.05, 0.1, 14))
|
||||
show screen endingtext(list_credits_titles[13], tf_credits_moveinright(0.05, 0.1, 14), text_size=__("100=Stock Sounds by"))
|
||||
show screen endingtext(display_credits_names(13, start_index=10, end_index=13), tf_credits_moveinleft(0.45, 0.3, 7), 1.0) as endingtext2
|
||||
|
||||
pause 7
|
||||
@ -1123,7 +1158,7 @@ label e4credits_16:
|
||||
linear 0.1 yoffset -1
|
||||
repeat
|
||||
|
||||
show screen endingtext(list_credits_titles[14], tf_credits_moveinright(0.2, 0.1, 7))
|
||||
show screen endingtext(list_credits_titles[14], tf_credits_moveinright(0.2, 0.1, 7), text_size=__("100=Stock sounds acquired at"))
|
||||
show screen endingtext(display_credits_names(14), tf_credits_moveinleft(0.9, 0.3, 7), 1.0) as endingtext2
|
||||
|
||||
pause 7.5
|
||||
@ -1159,7 +1194,7 @@ label e4credits_final:
|
||||
xpos 0.12 ypos 0.24 alpha 0.0
|
||||
linear 0.5 alpha ALPHA_CONTROLLER
|
||||
|
||||
show screen endingtext(list_credits_titles[15], tf_credits_moveinright(0.15, 0.15, 15.25))
|
||||
show screen endingtext(list_credits_titles[15], tf_credits_moveinright(0.15, 0.15, 15.25), text_size=__("100=Special Thanks"))
|
||||
show screen endingtext(display_credits_names(15, end_index=4), tf_credits_moveinleft(0.85, 0.25, 7), 1.0) as endingtext2
|
||||
|
||||
pause 7.5
|
||||
|
@ -31,9 +31,17 @@ define audio.mus_introspective_night = "<loop 39.801833>" + DEFAULT_MUSIC_FILEPA
|
||||
define audio.mus_school_somber = "<loop 1.1363955>" + DEFAULT_MUSIC_FILEPATH + "mus_school_somber" + DEFAULT_MUSIC_EXTENSION
|
||||
define audio.mus_remorse = "<loop 81.832583>" + DEFAULT_MUSIC_FILEPATH + "mus_remorse" + DEFAULT_MUSIC_EXTENSION
|
||||
define audio.mus_complete = "<loop 2.580167>" + DEFAULT_MUSIC_FILEPATH + "mus_complete" + DEFAULT_MUSIC_EXTENSION
|
||||
define audio.mus_boring = "<loop 20.571>" + DEFAULT_MUSIC_FILEPATH + "mus_boring" + DEFAULT_MUSIC_EXTENSION
|
||||
define audio.mus_intense = "<loop 26.691>" + DEFAULT_MUSIC_FILEPATH + "mus_intense" + DEFAULT_MUSIC_EXTENSION
|
||||
define audio.mus_romance3 = "<loop 97.079>" + DEFAULT_MUSIC_FILEPATH + "mus_romance3" + DEFAULT_MUSIC_EXTENSION
|
||||
define audio.mus_introspective1 = "<loop 48>" + DEFAULT_MUSIC_FILEPATH + "mus_introspective1" + DEFAULT_MUSIC_EXTENSION
|
||||
define audio.mus_dress = "<loop 192>" + DEFAULT_MUSIC_FILEPATH + "mus_dress" + DEFAULT_MUSIC_EXTENSION
|
||||
define audio.mus_olivia = "<loop 121.905>" + DEFAULT_MUSIC_FILEPATH + "mus_olivia" + DEFAULT_MUSIC_EXTENSION
|
||||
define audio.mus_happy1 = "<loop 45>" + DEFAULT_MUSIC_FILEPATH + "mus_happy1" + DEFAULT_MUSIC_EXTENSION
|
||||
define audio.mus_credits_e4 = "<loop 138.729271>" + DEFAULT_MUSIC_FILEPATH + "mus_credits_e4" + DEFAULT_MUSIC_EXTENSION
|
||||
|
||||
define audio.mus_chill2 = "<loop 5.97428>" + DEFAULT_MUSIC_FILEPATH + "mus_chill2" + DEFAULT_MUSIC_EXTENSION
|
||||
define audio.mus_happy1 = "<loop 10.68202>" + DEFAULT_MUSIC_FILEPATH + "mus_happy1" + DEFAULT_MUSIC_EXTENSION
|
||||
define audio.mus_happy2 = "<loop 10.68202>" + DEFAULT_MUSIC_FILEPATH + "mus_happy2" + DEFAULT_MUSIC_EXTENSION
|
||||
define audio.mus_damien = "<loop 18.63127>" + DEFAULT_MUSIC_FILEPATH + "mus_damien" + DEFAULT_MUSIC_EXTENSION
|
||||
define audio.mus_upbeat = "<loop 0.019>" + DEFAULT_MUSIC_FILEPATH + "mus_upbeat" + DEFAULT_MUSIC_EXTENSION
|
||||
define audio.mus_chill_thinking = "<loop 9.989292>" + DEFAULT_MUSIC_FILEPATH + "mus_chill_thinking" + DEFAULT_MUSIC_EXTENSION
|
||||
|
@ -1480,7 +1480,9 @@ layeredimage olivia hmph:
|
||||
xanchor 0.5 yoffset -150 mesh True
|
||||
gl_drawable_resolution False
|
||||
|
||||
always "spr_olivia_tail_normal_hmph"
|
||||
group tails:
|
||||
attribute tailsock "spr_olivia_tail_tailsock_neutral"
|
||||
attribute notailsock default "spr_olivia_tail_normal_hmph"
|
||||
|
||||
group wheelchair_back:
|
||||
attribute wheelchair default "spr_olivia_wheelchair_back"
|
||||
@ -2445,15 +2447,15 @@ layeredimage vinny:
|
||||
attribute unswag "spr_null"
|
||||
|
||||
group macaroni_left: #see images.rpy for definitions for the macaroni
|
||||
attribute macaroni "macaroni_left"
|
||||
attribute macaroni_up "macaroni_left_up"
|
||||
attribute macaronibroken "macaroni_left_broken"
|
||||
attribute macaroni "spr_macaroni_left" xoffset 250 yoffset 820
|
||||
attribute macaroni_up "spr_macaroni_left" xoffset 250 yoffset 760
|
||||
attribute macaronibroken "spr_macaroni_left" xoffset 220 yoffset 820
|
||||
attribute nomacaroni "spr_null"
|
||||
|
||||
group macaroni_right:
|
||||
attribute macaroni "macaroni_right"
|
||||
attribute macaroni_up "macaroni_right_up"
|
||||
attribute macaronibroken "macaroni_right_broken"
|
||||
attribute macaroni "spr_macaroni_right" xoffset 250 yoffset 820
|
||||
attribute macaroni_up "spr_macaroni_right" xoffset 250 yoffset 760
|
||||
attribute macaronibroken "spr_macaroni_right" xoffset 280 yoffset 820
|
||||
attribute nomacaroni "spr_null"
|
||||
|
||||
|
||||
|
@ -326,56 +326,19 @@ image full_box:
|
||||
contains:
|
||||
"bg_box_front"
|
||||
|
||||
# Vinny's Macaroni
|
||||
image macaroni_right:
|
||||
"spr_macaroni_right"
|
||||
xoffset 250 yoffset 820
|
||||
|
||||
image macaroni_left:
|
||||
contains:
|
||||
"spr_macaroni_left_base"
|
||||
xoffset 250 yoffset 820
|
||||
contains:
|
||||
"spr_macaroni_left_text"
|
||||
xoffset 250 yoffset 820
|
||||
|
||||
image macaroni_right_broken:
|
||||
"spr_macaroni_right"
|
||||
xoffset 280 yoffset 820
|
||||
|
||||
image macaroni_left_broken:
|
||||
contains:
|
||||
"spr_macaroni_left_base"
|
||||
xoffset 220 yoffset 820
|
||||
contains:
|
||||
"spr_macaroni_left_text"
|
||||
xoffset 220 yoffset 820
|
||||
|
||||
image macaroni_right_up:
|
||||
"spr_macaroni_right"
|
||||
xoffset 250 yoffset 820
|
||||
"spr_macaroni_right"
|
||||
yoffset 760
|
||||
#TODO: add transitions to this so it doesn't suck!
|
||||
#easein_cubic yoffset 760
|
||||
|
||||
image macaroni_left_up:
|
||||
contains:
|
||||
"spr_macaroni_left_base"
|
||||
xoffset 250 yoffset 820
|
||||
"spr_macaroni_left_base"
|
||||
yoffset 760
|
||||
contains:
|
||||
"spr_macaroni_left_text"
|
||||
xoffset 250 yoffset 820
|
||||
"spr_macaroni_left_text"
|
||||
yoffset 760
|
||||
|
||||
#
|
||||
# DO NOT USE THE contains METHOD FOR PROPS ATTACHED TO CHARACTERS IN THE characters.rpy FILE.
|
||||
# For some reason, they bug out on positoning and alignment if you do, so use Composte() instead.
|
||||
#
|
||||
|
||||
# Vinny's Macaroni
|
||||
image spr_macaroni_left = Composite(
|
||||
(232, 147),
|
||||
(0, 0), "spr_macaroni_left_base",
|
||||
(0, 0), "spr_macaroni_left_text"
|
||||
)
|
||||
|
||||
|
||||
# Inco's grocery bag
|
||||
image spr_mug_damien = Composite(
|
||||
(195, 206),
|
||||
|
@ -1,6 +1,7 @@
|
||||
python early in cds_utils:
|
||||
from renpy import store
|
||||
|
||||
# if store.is_renpy_version_or_above(7, 6, 0)
|
||||
Lexer = renpy.lexer.Lexer if renpy.version_tuple >= ((7, 6) if renpy.compat.PY2 else (8, 1)) else renpy.parser.Lexer
|
||||
|
||||
def null_parser(l):
|
||||
@ -91,7 +92,7 @@ python early in phone._lint:
|
||||
error("audio '{}' isn't loadable.".format(a))
|
||||
|
||||
python early in phone:
|
||||
from renpy.store import cds_utils
|
||||
from renpy.store import cds_utils
|
||||
|
||||
class _RawPhoneMessage(cds_utils.Statement):
|
||||
__slots__ = ("sender", "message", "delay")
|
||||
@ -148,10 +149,12 @@ python early in phone:
|
||||
self.delay = delay
|
||||
|
||||
def execute(self):
|
||||
discussion.label(self.label, eval(self.delay, store.__dict__))
|
||||
delay = config.default_label_delay if self.delay is None else eval(self.delay, store.__dict__)
|
||||
discussion.label(self.label, delay)
|
||||
|
||||
def lint(self):
|
||||
_lint.eval(self.delay)
|
||||
if self.delay is not None:
|
||||
_lint.eval(self.delay)
|
||||
|
||||
def get_translatable_strings(self):
|
||||
return [self.label]
|
||||
@ -166,7 +169,8 @@ python early in phone:
|
||||
|
||||
def execute(self):
|
||||
globals = store.__dict__
|
||||
discussion.date(delay=eval(self.delay, globals), auto=eval(self.auto, globals), **{k: eval(v, globals) for k, v in self.kwargs.items()})
|
||||
delay = config.default_label_delay if self.delay is None else eval(self.delay, globals)
|
||||
discussion.date(delay=delay, auto=eval(self.auto, globals), **{k: eval(v, globals) for k, v in self.kwargs.items()})
|
||||
|
||||
def lint(self):
|
||||
month = _lint.eval(self.kwargs["month"])
|
||||
@ -195,7 +199,8 @@ python early in phone:
|
||||
_lint.error("'{}' isn't a valid second.".format(second))
|
||||
|
||||
_lint.eval(self.kwargs["year"])
|
||||
_lint.eval(self.delay)
|
||||
if self.delay is not None:
|
||||
_lint.eval(self.delay)
|
||||
_lint.eval(self.auto)
|
||||
|
||||
class _RawPhoneTyping(cds_utils.Statement):
|
||||
@ -319,7 +324,19 @@ python early in phone:
|
||||
|
||||
class _RawPhonePass(cds_utils.Statement):
|
||||
def execute(self):
|
||||
store.pause()
|
||||
pass
|
||||
|
||||
class _RawPhonePause(cds_utils.Statement):
|
||||
__slots__ = ("duration",)
|
||||
|
||||
def __init__(self, duration):
|
||||
self.duration = duration
|
||||
|
||||
def execute(self):
|
||||
store.pause(eval(self.duration, store.__dict__))
|
||||
|
||||
def lint(self):
|
||||
_lint.eval(self.duration)
|
||||
|
||||
# class _RawPhoneRenpy(cds_utils.Statement):
|
||||
# __slots__ = ("nodes",)
|
||||
@ -621,12 +638,13 @@ python early in phone:
|
||||
|
||||
if register: return _RawPhoneRegisterLabel(label)
|
||||
|
||||
delay = "0.5" if not ll.keyword("delay") else ll.require(ll.simple_expression)
|
||||
delay = None if not ll.keyword("delay") else ll.require(ll.simple_expression)
|
||||
return _RawPhoneLabel(label, delay)
|
||||
|
||||
def _parse_phone_date(ll, register):
|
||||
kwargs = {time_thing: "None" for time_thing in ("month", "day", "year", "hour", "minute", "second")}
|
||||
kwargs["auto"] = "False"
|
||||
kwargs["delay"] = None
|
||||
seen = set()
|
||||
|
||||
while True:
|
||||
@ -652,11 +670,13 @@ python early in phone:
|
||||
break
|
||||
|
||||
auto = kwargs.pop("auto")
|
||||
delay = kwargs.pop("delay")
|
||||
|
||||
if register:
|
||||
if delay is not None:
|
||||
renpy.error("'delay' can't be used here")
|
||||
return _RawPhoneRegisterDate(kwargs, auto)
|
||||
|
||||
delay = "0.5" if not ll.keyword("delay") else ll.require(ll.simple_expression)
|
||||
return _RawPhoneDate(kwargs, delay, auto)
|
||||
|
||||
def _parse_phone_typing(ll):
|
||||
@ -820,6 +840,10 @@ python early in phone:
|
||||
if delay is None: delay = "None"
|
||||
return _RawPhoneAudio(sender, audio, time, delay)
|
||||
|
||||
def _parse_phone_pause(ll):
|
||||
duration = ll.simple_expression()
|
||||
return _RawPhonePause(duration or "None")
|
||||
|
||||
# def _parse_phone_renpy(ll):
|
||||
# ll.require(":")
|
||||
# ll.expect_eol()
|
||||
@ -863,6 +887,9 @@ python early in phone:
|
||||
elif ll.keyword("pass"):
|
||||
statement = _RawPhonePass()
|
||||
|
||||
elif ll.keyword("pause"):
|
||||
statement = _parse_phone_pause(ll)
|
||||
|
||||
# elif ll.keyword("renpy"):
|
||||
# statement = _parse_phone_renpy(ll)
|
||||
|
||||
@ -925,9 +952,12 @@ python early in phone:
|
||||
|
||||
return _RawPhoneDiscussion(gc, statements)
|
||||
|
||||
def _predict_phone_discussion(rd):
|
||||
renpy.predict_screen("phone_message")
|
||||
return [ ]
|
||||
# This and the statement that calls this function is stubbed out, otherwise a bug happens where the game crashes when advancing to fast when pulling up the phone
|
||||
# Not fixed as of EMR Phone 3.2.2
|
||||
|
||||
#def _predict_phone_discussion(rd):
|
||||
# renpy.predict_screen("phone_discussion")
|
||||
# return [ ]
|
||||
|
||||
def _phone_execute_init(rv):
|
||||
for statement in rv.statements:
|
||||
@ -942,7 +972,7 @@ python early in phone:
|
||||
execute_init=_phone_execute_init,
|
||||
translation_strings=cds_utils.get_translatable_strings,
|
||||
lint=cds_utils.lint,
|
||||
predict=_predict_phone_discussion
|
||||
#predict=_predict_phone_discussion
|
||||
)
|
||||
|
||||
########################################################
|
||||
@ -960,20 +990,46 @@ python early in phone:
|
||||
|
||||
def _parse_phone_call(l):
|
||||
rv = l.require(l.simple_expression)
|
||||
video = False
|
||||
nosave = False
|
||||
|
||||
while not l.eol():
|
||||
state = l.checkpoint()
|
||||
thing = l.word()
|
||||
|
||||
if thing == "video":
|
||||
if video:
|
||||
l.revert(state)
|
||||
l.error("video clause already given")
|
||||
else:
|
||||
video = True
|
||||
|
||||
elif thing == "nosave":
|
||||
if nosave:
|
||||
l.revert(state)
|
||||
l.error("nosave clause already given")
|
||||
else:
|
||||
nosave = True
|
||||
|
||||
else:
|
||||
l.revert(state)
|
||||
l.error("unknown property %s" % thing)
|
||||
|
||||
|
||||
l.expect_eol()
|
||||
l.expect_noblock("phone call")
|
||||
return rv
|
||||
return rv, video, nosave
|
||||
|
||||
def _execute_phone_call(c):
|
||||
c = character.character(eval(c, store.__dict__))
|
||||
calls.call(c)
|
||||
def _execute_phone_call(tu):
|
||||
c = character.character(eval(tu[0], store.__dict__))
|
||||
calls.call(c, tu[1], tu[2])
|
||||
|
||||
def _predict_phone_call(c):
|
||||
renpy.predict_screen("phone_call")
|
||||
def _predict_phone_call(tu):
|
||||
renpy.predict_screen("phone_call", video=tu[1])
|
||||
return [ ]
|
||||
|
||||
def _lint_phone_call(c):
|
||||
_lint.character(c)
|
||||
def _lint_phone_call(tu):
|
||||
_lint.character(tu[0])
|
||||
|
||||
renpy.register_statement(
|
||||
"phone call",
|
||||
@ -1047,20 +1103,21 @@ python early in phone:
|
||||
|
||||
# soooooooooooooooooooooooooooooooooooooooooooooooo clunky
|
||||
class _RawInitPhoneRegister(_RawPhoneRegister):
|
||||
__slots__ = ("name", "icon", "key", "chars", "default_statement")
|
||||
__slots__ = ("name", "icon", "key", "chars", "transient", "default_statement")
|
||||
|
||||
def __init__(self, gc, statements, name, icon, key, chars, default_statement):
|
||||
def __init__(self, gc, statements, name, icon, key, chars, transient, default_statement):
|
||||
super(_RawInitPhoneRegister, self).__init__(gc, statements)
|
||||
self.name = name
|
||||
self.icon = icon
|
||||
self.key = key
|
||||
self.chars = chars
|
||||
self.transient = transient
|
||||
self.default_statement = default_statement
|
||||
|
||||
def execute(self):
|
||||
if self.default_statement is not None:
|
||||
self.default_statement.execute()
|
||||
_run_on_start(self._execute, ("phone define gc", self.gc if self.gc is not None else str(self.key)))
|
||||
execute_default(self._execute, ("phone define gc", self.gc if self.gc is not None else str(self.key)))
|
||||
|
||||
def _execute(self):
|
||||
gc = None
|
||||
@ -1070,7 +1127,7 @@ python early in phone:
|
||||
gc = getattr(store, self.default_statement.varname)
|
||||
else:
|
||||
if self.name is not None:
|
||||
gc = group_chat.GroupChat(self.name, eval(self.icon, globals), eval(self.key, globals))
|
||||
gc = group_chat.GroupChat(self.name, eval(self.icon, globals), eval(self.key, globals), transient=self.transient)
|
||||
|
||||
if gc is not None:
|
||||
for char in self.chars:
|
||||
@ -1108,6 +1165,7 @@ python early in phone:
|
||||
key = None
|
||||
icon = None
|
||||
chars = [ ]
|
||||
transient = False
|
||||
_as = None
|
||||
default_statement = None
|
||||
|
||||
@ -1144,6 +1202,11 @@ python early in phone:
|
||||
dl.error("character '{}' already given".format(char))
|
||||
chars.append(char)
|
||||
|
||||
elif p == "transient":
|
||||
if transient:
|
||||
dl.error("'transient' property already given")
|
||||
transient = True
|
||||
|
||||
elif p == "as":
|
||||
if _as is not None:
|
||||
dl.error("'as' property already given")
|
||||
@ -1157,19 +1220,20 @@ python early in phone:
|
||||
dl.error("expected 'key' property")
|
||||
|
||||
if icon is None:
|
||||
icon = 'phone.config.basedir + "default_icon.png"'
|
||||
icon = 'phone.asset("default_icon.png")'
|
||||
|
||||
if _as is not None:
|
||||
filename, linenumber = l.get_location()
|
||||
|
||||
global _INIT_PHONE_REGISTER_PRIORITY
|
||||
string = "{init} {_as} = phone.group_chat.GroupChat('{name}', {icon}, {key})" \
|
||||
string = "{init} {_as} = phone.group_chat.GroupChat('{name}', {icon}, {key}, transient={transient})" \
|
||||
.format(
|
||||
init=_INIT_PHONE_REGISTER_PRIORITY,
|
||||
_as=_as,
|
||||
name=name,
|
||||
icon=icon,
|
||||
key=key,
|
||||
transient=transient,
|
||||
)
|
||||
|
||||
lexer = cds_utils.Lexer(
|
||||
@ -1184,7 +1248,7 @@ python early in phone:
|
||||
if not statements and not no_gc:
|
||||
ll.error("expected at least one statement")
|
||||
|
||||
return _RawInitPhoneRegister(gc, statements, name, icon, key, chars, default_statement)
|
||||
return _RawInitPhoneRegister(gc, statements, name, icon, key, chars, transient, default_statement)
|
||||
|
||||
def _translation_strings_init_phone_register(ripr):
|
||||
rv = _translation_strings_phone_register(ripr)
|
||||
|
@ -2,7 +2,7 @@ python early in phone:
|
||||
from renpy import store
|
||||
from store import config as renpy_config # phone.config is a substore
|
||||
|
||||
__version__ = (3, 1, 0)
|
||||
__version__ = (3, 2, 2)
|
||||
__author__ = "Elckarow#8399" # smh my head my head
|
||||
|
||||
init -150 python in phone:
|
||||
@ -26,7 +26,7 @@ init -150 python in phone:
|
||||
|
||||
import time
|
||||
def format_time(hour, minute):
|
||||
return time.strftime(__(config.time_format), time.struct_time((1, 1, 1, hour, minute, 0, 1, 0, 0)))
|
||||
return time.strftime(__(config.time_format), time.gmtime(hour * 3600 + minute * 60))
|
||||
|
||||
transform -150 _fits(size):
|
||||
subpixel True xysize (size, size) fit "contain"
|
||||
@ -98,7 +98,7 @@ init -100 python in phone:
|
||||
menu = not first_call
|
||||
|
||||
if needs_rollback:
|
||||
renpy.rollback(True)
|
||||
renpy.rollback(force=True, greedy=False)
|
||||
|
||||
return rv
|
||||
|
||||
@ -115,6 +115,36 @@ init -100 python in phone:
|
||||
at_list = [at_list]
|
||||
|
||||
renpy.show_layer_at(at_list=at_list, layer=layer, camera=camera, reset=reset)
|
||||
|
||||
def short_name(s, length):
|
||||
s = renpy.substitute(s)
|
||||
if len(s) > length:
|
||||
s = s[:length - 3] + "..."
|
||||
|
||||
return s
|
||||
|
||||
import os
|
||||
@renpy.pure
|
||||
def path_join(*paths):
|
||||
return os.path.join(*paths).replace("\\", "/")
|
||||
|
||||
@renpy.pure
|
||||
def asset(path):
|
||||
return path_join(config.basedir, path)
|
||||
|
||||
def execute_default(f, id):
|
||||
def run(load):
|
||||
if id not in _defaults_ran:
|
||||
_defaults_ran.add(id)
|
||||
f()
|
||||
if load: renpy.block_rollback()
|
||||
|
||||
renpy_config.start_callbacks.append(renpy.partial(run, load=False))
|
||||
renpy_config.after_load_callbacks.append(renpy.partial(run, load=True))
|
||||
|
||||
# a set() object
|
||||
# renamed it because why not
|
||||
default -999 phone._defaults_ran = phone._id_ran_on_start
|
||||
|
||||
default -100 phone._stack_depth = 0
|
||||
default -100 phone._current_screen = None
|
||||
@ -122,7 +152,7 @@ default broken_phone = False
|
||||
|
||||
# The base screen for all phone screens.
|
||||
screen _phone(xpos=0.5, xanchor=0.5, ypos=0.05, yanchor=0.0, horizontal=False):
|
||||
frame style "empty":
|
||||
frame style "empty" modal True:
|
||||
at transform:
|
||||
subpixel True zoom gui.phone_zoom * (1.12 if horizontal else 1.0)
|
||||
xpos xpos xanchor xanchor
|
||||
@ -148,7 +178,7 @@ screen _phone(xpos=0.5, xanchor=0.5, ypos=0.05, yanchor=0.0, horizontal=False):
|
||||
|
||||
fixed style "empty":
|
||||
for o in phone.config.overlay_screens:
|
||||
use expression o
|
||||
use expression o
|
||||
|
||||
# https://www.renpy.org/doc/html/incompatible.html#incompatible-7-5-2
|
||||
# the thing just above
|
||||
@ -169,7 +199,7 @@ screen _phone(xpos=0.5, xanchor=0.5, ypos=0.05, yanchor=0.0, horizontal=False):
|
||||
xpos=0.501
|
||||
)
|
||||
else:
|
||||
add phone.config.basedir + "phone_frame.png" at Transform(
|
||||
add phone.asset("phone_frame.png") at Transform(
|
||||
subpixel=True,
|
||||
align=(0.5, 0.5),
|
||||
rotate=-90 * horizontal,
|
||||
@ -178,7 +208,7 @@ screen _phone(xpos=0.5, xanchor=0.5, ypos=0.05, yanchor=0.0, horizontal=False):
|
||||
ypos=0.685,
|
||||
xpos=0.501
|
||||
)
|
||||
add phone.config.basedir + "phone_glare.png" at Transform(
|
||||
add phone.asset("phone_glare.png") at Transform(
|
||||
subpixel=True,
|
||||
align=(0.5, 0.5),
|
||||
rotate=-90 * horizontal,
|
||||
@ -188,34 +218,10 @@ screen _phone(xpos=0.5, xanchor=0.5, ypos=0.05, yanchor=0.0, horizontal=False):
|
||||
xpos=0.501,
|
||||
alpha=0.1
|
||||
)
|
||||
|
||||
on "hide" action (
|
||||
SetVariable("phone.system.at_list", []),
|
||||
)
|
||||
|
||||
# Deprecated stuff
|
||||
label _phone_register:
|
||||
$ raise Exception("The label '_phone_register' isn't needed anymore")
|
||||
|
||||
init -500 python in phone:
|
||||
def register_group_chat(group, *keys):
|
||||
raise Exception("The 'phone.register_group_chat' function isn't needed anymore")
|
||||
|
||||
def register(f):
|
||||
raise Exception("The `phone.register` decorator isn't used anymore. (function being decorated: {})".format(f.__name__))
|
||||
|
||||
def _run_on_start(f, id):
|
||||
def run(load):
|
||||
if id not in _id_ran_on_start:
|
||||
_id_ran_on_start.add(id)
|
||||
f()
|
||||
if load: renpy.block_rollback()
|
||||
|
||||
renpy_config.start_callbacks.append(renpy.partial(run, load=False))
|
||||
renpy_config.after_load_callbacks.append(renpy.partial(run, load=True))
|
||||
|
||||
default -1000 phone._id_ran_on_start = set()
|
||||
|
||||
init 1500:
|
||||
# narrator is guarenteed to exist at init 1400
|
||||
# see renpy/common/00definitions.rpy
|
||||
@ -231,4 +237,11 @@ init 1500:
|
||||
raise Exception("store.PhoneReturn is a reserved name. (value is %r)" % store.PhoneReturn)
|
||||
store.PhoneReturn = PhoneReturn
|
||||
|
||||
|
||||
if store.is_renpy_version_or_above(7, 6, 0):
|
||||
renpy_config.detached_layers.append(config.video_call_layer)
|
||||
|
||||
# https://github.com/renpy/renpy/issues/5044
|
||||
renpy_config.layer_clipping[config.video_call_layer] = (0, 0, renpy_config.screen_width, renpy_config.screen_height)
|
||||
|
||||
# previous name, when the function it's used in was undocumented
|
||||
default -1000 phone._id_ran_on_start = set()
|
||||
|
@ -5,16 +5,20 @@ screen app_base(action=NullAction()):
|
||||
ysize 50 + (gui.phone_status_bar_height * bool(phone.config.status_bar))
|
||||
top_padding 10 + (gui.phone_status_bar_height * bool(phone.config.status_bar))
|
||||
textbutton _("< Back"):
|
||||
xoffset 20
|
||||
action (action, PhoneReturn())
|
||||
sensitive phone.menu
|
||||
|
||||
|
||||
transclude
|
||||
|
||||
style app_base_frame is empty:
|
||||
background "#F2F2F2"
|
||||
xfill True
|
||||
xpadding 10
|
||||
bottom_padding 10
|
||||
# bottom_padding has been changed from 10 and added top_padding to use a hacky way of visually centering the
|
||||
# top texts of the ui.
|
||||
bottom_padding 7
|
||||
top_padding 3
|
||||
|
||||
style app_base_hbox is empty:
|
||||
spacing 5
|
||||
@ -23,13 +27,13 @@ style app_base_hbox is empty:
|
||||
style app_base_text is empty:
|
||||
outlines [ ]
|
||||
yalign 0.5
|
||||
color "#000" size 19
|
||||
font phone.config.basedir + "Aller_Rg.ttf"
|
||||
color "#000" size 22
|
||||
font phone.asset("Aller_Rg.ttf")
|
||||
|
||||
style app_base_button is empty:
|
||||
yalign 0.5
|
||||
xalign 0.0
|
||||
|
||||
style app_base_button_text is app_base_text:
|
||||
color "#0094FF"
|
||||
size 18
|
||||
color "#0094FF"
|
||||
size 22
|
||||
|
@ -1,25 +1,18 @@
|
||||
init -100 python in phone.application:
|
||||
from renpy import store
|
||||
from store import (
|
||||
Gradient, RoundedFrame, Transform,
|
||||
Gradient, RoundedCorners, Transform,
|
||||
Text, phone, NullAction, Fixed, gui, Null, Flatten
|
||||
)
|
||||
from store.phone import config
|
||||
|
||||
def IconBackground(d, **kwargs):
|
||||
return RoundedFrame(
|
||||
return RoundedCorners(
|
||||
d, radius=gui.phone_application_rounded_corners_radius,
|
||||
xysize=(gui.phone_application_icon_size, gui.phone_application_icon_size),
|
||||
**kwargs
|
||||
)
|
||||
|
||||
def Borders(color, width):
|
||||
return IconBackground(
|
||||
Null(gui.phone_application_icon_size, gui.phone_application_icon_size),
|
||||
outline_color=color,
|
||||
outline_width=width
|
||||
)
|
||||
|
||||
def GradientBackground(start_color, end_color, theta=0):
|
||||
return IconBackground(Gradient(start_color, end_color, theta))
|
||||
|
||||
@ -78,7 +71,7 @@ init -100 python in phone.application:
|
||||
Returns `True` if added, `False` if it failed, or `None` if renpy is still init phase and we can't know.
|
||||
"""
|
||||
if renpy.is_init_phase():
|
||||
phone._run_on_start(renpy.partial(add_application, app, page, key), ("_phone_add_app", app.name, page, key))
|
||||
phone.execute_default(renpy.partial(add_application, app, page, key), ("_phone_add_app", app.name, page, key))
|
||||
return None
|
||||
|
||||
if not isinstance(app, Application):
|
||||
@ -111,7 +104,7 @@ init -100 python in phone.application:
|
||||
|
||||
def add_app_to_all_characters(app, page=0):
|
||||
if renpy.is_init_phase():
|
||||
phone._run_on_start(renpy.partial(add_app_to_all_characters, app, page), ("_phone_add_app", app.name, page))
|
||||
phone.execute_default(renpy.partial(add_app_to_all_characters, app, page), ("_phone_add_app", app.name, page))
|
||||
return None
|
||||
|
||||
rv = False
|
||||
@ -141,10 +134,7 @@ screen phone():
|
||||
current_page = min(current_page, max_page)
|
||||
|
||||
fixed style_prefix "phone_main":
|
||||
frame style "empty":
|
||||
align (1.0, 0.0) padding (10, 10)
|
||||
background "#474747"
|
||||
textbutton "Quit" action PhoneReturn()
|
||||
button style "empty" xysize (1.0, 1.0) action If(coords_to_move is None, PhoneReturn(), SetScreenVariable("coords_to_move", None))
|
||||
|
||||
if coords_to_move is not None:
|
||||
key "K_ESCAPE" action SetScreenVariable("coords_to_move", None)
|
||||
@ -156,7 +146,7 @@ screen phone():
|
||||
rotate -90 transform_anchor True
|
||||
xysize (150, 30) matrixcolor TintMatrix("#474343ee")
|
||||
action SetScreenVariable("current_page", current_page - 1)
|
||||
add phone.config.basedir + "arrow_icon.png"
|
||||
add phone.asset("arrow_icon.png")
|
||||
|
||||
if current_page != max_page:
|
||||
button:
|
||||
@ -165,7 +155,7 @@ screen phone():
|
||||
rotate 90 transform_anchor True
|
||||
xysize (150, 30) matrixcolor TintMatrix("#474343ee")
|
||||
action SetScreenVariable("current_page", current_page + 1)
|
||||
add phone.config.basedir + "arrow_icon.png"
|
||||
add phone.asset("arrow_icon.png")
|
||||
|
||||
use _phone():
|
||||
style_prefix "phone_main"
|
||||
@ -187,7 +177,7 @@ screen phone():
|
||||
vbox:
|
||||
hbox xalign 0.5 spacing 13:
|
||||
for i in range(max_page + 1):
|
||||
add phone.config.basedir + "circle.png":
|
||||
add phone.asset("circle.png"):
|
||||
at transform:
|
||||
subpixel True xysize (10, 10)
|
||||
matrixcolor TintMatrix("#4e4e4e")
|
||||
@ -255,10 +245,7 @@ screen _phone_application_button(app, app_coords, coords_to_move):
|
||||
button:
|
||||
at (_phone_move_application_selected if app_coords == coords_to_move else _phone_move_application)
|
||||
|
||||
if app is None:
|
||||
add phone.application.Borders("#ffffffcc", 5)
|
||||
else:
|
||||
add phone.application.IconBackground("#ffffffcc")
|
||||
add phone.application.IconBackground("#ffffffcc")
|
||||
|
||||
action [
|
||||
Function(phone.application.move_application, coords_to_move, app_coords),
|
||||
@ -298,7 +285,7 @@ style _phone_application_button_vbox is empty:
|
||||
style _phone_application_button_text is empty:
|
||||
text_align 0.5 xalign 0.5
|
||||
outlines [ ] color "#000"
|
||||
size 12 font phone.config.basedir + "Metropolis-Regular.otf"
|
||||
size 12 font phone.asset("Metropolis-Regular.otf")
|
||||
line_spacing 0
|
||||
|
||||
style _phone_application_button_fixed is empty:
|
||||
|
@ -110,25 +110,27 @@ init -100 python in phone.calendar:
|
||||
def day_name(year, month, day):
|
||||
return days[calendar.weekday(year, month, day)]
|
||||
|
||||
def add_calendar(calendar, key=None):
|
||||
def add_calendar(year, month, key=None, first_day=SUNDAY):
|
||||
if renpy.is_init_phase():
|
||||
phone._run_on_start(renpy.partial(add_calendar, calendar, key), ("_phone_add_calendar", calendar.month, calendar.year, key))
|
||||
phone.execute_default(renpy.partial(add_calendar, year=year, month=month, key=key, first_day=first_day), ("_phone_add_calendar", month, year, key))
|
||||
else:
|
||||
key = character.character(key).key
|
||||
store.phone.data[key]["calendars"].append(calendar)
|
||||
|
||||
def add_calendar_to_all_characters(calendar):
|
||||
if get_calendar(year=year, month=month, key=key) is not None:
|
||||
raise Exception("a calendar for the year {} and month {} already exists for the *character* {}" \
|
||||
.format(year, month, key))
|
||||
|
||||
calendars = store.phone.data[key]["calendars"]
|
||||
calendars.append(Calendar(year=year, month=month, first_day=first_day))
|
||||
|
||||
calendars.sort(key=lambda c: (c.year, c.month))
|
||||
|
||||
def add_calendar_to_all_characters(year, month, first_day=SUNDAY):
|
||||
if renpy.is_init_phase():
|
||||
phone._run_on_start(renpy.partial(add_calendar_to_all_characters, calendar), ("_phone_add_calendar", calendar.month, calendar.year))
|
||||
phone.execute_default(renpy.partial(add_calendar_to_all_characters, year=year, month=month, first_day=first_day), ("_phone_add_calendar", month, year))
|
||||
else:
|
||||
l = calendar.lenght(False)
|
||||
|
||||
for key in character._characters:
|
||||
_calendar = Calendar(calendar.month, calendar.year, calendar.firstweekday)
|
||||
for i in range(l):
|
||||
_calendar[i].description = calendar[i].description
|
||||
|
||||
add_calendar(_calendar, key)
|
||||
add_calendar(year=year, month=month, first_day=first_day, key=key)
|
||||
|
||||
_calendar_button_background = At(config.basedir + "circle.png", store._fits(None))
|
||||
|
||||
@ -139,11 +141,31 @@ init -100 python in phone.calendar:
|
||||
return calendar
|
||||
return None
|
||||
|
||||
def _calendar_default_index(m):
|
||||
n = config.default_calendar_index
|
||||
|
||||
if n is True:
|
||||
pov_key = store.pov_key
|
||||
date = system.get_date()
|
||||
|
||||
c = get_calendar(year=date.year, month=date.month, key=pov_key)
|
||||
|
||||
if c is None:
|
||||
raise Exception("no calendar with the year {} and month {} exists for the *character* {}".format(year, month, pov_key))
|
||||
|
||||
n = phone.data[pov_key]["calendars"].index(c)
|
||||
|
||||
elif n < 0:
|
||||
n = m + n
|
||||
|
||||
return n
|
||||
|
||||
screen phone_calendars():
|
||||
default calendars = phone.data[pov_key]["calendars"]
|
||||
default m = len(calendars) - 1
|
||||
default n = m
|
||||
default n = phone.calendar._calendar_default_index(m + 1)
|
||||
default selected_entry = None
|
||||
default yadj = ui.adjustment()
|
||||
|
||||
$ calendar = calendars[n]
|
||||
|
||||
@ -185,6 +207,7 @@ screen phone_calendars():
|
||||
SetScreenVariable("selected_entry", entry),
|
||||
SetScreenVariable("selected_entry", None)
|
||||
),
|
||||
Function(yadj.change, 0),
|
||||
SelectedIf(selected_entry is entry)
|
||||
)
|
||||
|
||||
@ -202,15 +225,16 @@ screen phone_calendars():
|
||||
|
||||
side "l c r" xalign 0.5:
|
||||
textbutton "<" action If(n != 0, (SetScreenVariable("n", n - 1), SetScreenVariable("selected_entry", None)))
|
||||
text _("[calendar.month_name]-[calendar.year]") size 25 xalign 0.5 text_align 0.5
|
||||
text _("[calendar.month_name!t]-[calendar.year]") size 25 xalign 0.5 text_align 0.5
|
||||
textbutton ">" action If(n != m, (SetScreenVariable("n", n + 1), SetScreenVariable("selected_entry", None)))
|
||||
|
||||
frame:
|
||||
frame at CurriedRoundedCorners(radius=(0, 25, 0, 25)):
|
||||
vbox spacing 3 at Flatten:
|
||||
text _("Notes:") size 22
|
||||
|
||||
viewport:
|
||||
draggable True mousewheel True
|
||||
yadjustment yadj
|
||||
|
||||
if selected_entry is not None:
|
||||
if selected_entry.description is not None:
|
||||
@ -232,7 +256,7 @@ style phone_calendar_button_text is empty:
|
||||
outlines []
|
||||
size 16
|
||||
align (0.5, 0.5) text_align 0.5
|
||||
font phone.config.basedir + "Aller_Rg.ttf"
|
||||
font phone.asset("Aller_Rg.ttf")
|
||||
|
||||
style phone_calendar_button_text_special is phone_calendar_button_text:
|
||||
size 12
|
||||
@ -254,7 +278,7 @@ style phone_calendar_notes_button_text is phone_calendar_notes_text:
|
||||
size 21
|
||||
|
||||
style phone_calendar_notes_frame is empty:
|
||||
background RoundedFrame("#e0e0e0", radius=(0, 25, 0, 25))
|
||||
background "#e0e0e0"
|
||||
padding (13, 7, 13, 0)
|
||||
xfill True ysize 180
|
||||
|
||||
|
@ -35,7 +35,7 @@ screen phone_call_history():
|
||||
|
||||
fixed:
|
||||
hbox style "empty" yalign 0.2 spacing 10:
|
||||
text char.short_name
|
||||
text phone.short_name(char.name, 26)
|
||||
if entry.duration is not None:
|
||||
text "-"
|
||||
text entry._duration_to_str()
|
||||
|
@ -16,11 +16,10 @@ init -100 python in phone.calls:
|
||||
from store.phone import character, config, show_layer_at, set_current_screen, system
|
||||
import time
|
||||
|
||||
# config.layer_at_transforms["phone_call"] = call_blur
|
||||
# config.layer_at_transforms["phone_call"] = Transform(matrixcolor=BrightnessMatrix(-0.21), blur=20)
|
||||
# config.hide_status_bar_screens.append("phone_call")
|
||||
|
||||
def call(caller):
|
||||
|
||||
def call(caller, video=False, nosave=False):
|
||||
global _current_caller
|
||||
if _current_caller is not None:
|
||||
raise Exception("can't have 2 phone calls at the same time")
|
||||
@ -28,13 +27,16 @@ init -100 python in phone.calls:
|
||||
# store.narrator = store._phone_narrator
|
||||
|
||||
store._window_hide()
|
||||
|
||||
set_current_screen("phone_call")
|
||||
show_layer_at([call_blur])
|
||||
renpy.show_screen("phone_call")
|
||||
renpy.with_statement(config.enter_transition)
|
||||
|
||||
renpy.show_screen("phone_call", video=video)
|
||||
renpy.with_statement(config.enter_transition)
|
||||
store._window_auto = True
|
||||
|
||||
|
||||
global _nosave
|
||||
_nosave = bool(nosave)
|
||||
|
||||
def end_call():
|
||||
store._window_hide()
|
||||
@ -50,9 +52,11 @@ init -100 python in phone.calls:
|
||||
|
||||
show_layer_at([call_unblur], reset=True)
|
||||
renpy.hide_screen("phone_call")
|
||||
if store.is_renpy_version_or_above(7, 5, 0):
|
||||
renpy.scene(config.video_call_layer)
|
||||
renpy.with_statement(config.exit_transition)
|
||||
set_current_screen(None)
|
||||
|
||||
set_current_screen(None)
|
||||
store._window_auto = True
|
||||
|
||||
class _CallEntry(object):
|
||||
@ -71,14 +75,19 @@ init -100 python in phone.calls:
|
||||
|
||||
date = system.get_date()
|
||||
|
||||
ch1 = phone.data[key1]["call_history"]
|
||||
ch1.append(_CallEntry(key2, date, duration))
|
||||
global _nosave
|
||||
if _nosave is not None and not _nosave:
|
||||
_nosave = None
|
||||
|
||||
ch1 = phone.data[key1]["call_history"]
|
||||
ch1.append(_CallEntry(key2, date, duration))
|
||||
|
||||
while len(ch1) > config.call_history_lenght: ch1.pop(0)
|
||||
|
||||
ch2 = phone.data[key2]["call_history"]
|
||||
ch2.append(_CallEntry(key1, date, duration))
|
||||
while len(ch1) > config.call_history_lenght: ch1.pop(0)
|
||||
|
||||
while len(ch2) > config.call_history_lenght: ch2.pop(0)
|
||||
ch2 = phone.data[key2]["call_history"]
|
||||
ch2.append(_CallEntry(key1, date, duration))
|
||||
|
||||
default -100 phone.calls._current_caller = None
|
||||
while len(ch2) > config.call_history_lenght: ch2.pop(0)
|
||||
|
||||
default -100 phone.calls._current_caller = None
|
||||
default -100 phone.calls._nosave = None
|
||||
|
@ -6,28 +6,35 @@ init -100 python in phone.calls:
|
||||
|
||||
default phone.calls._call_time_st = 0.0
|
||||
|
||||
screen phone_call():
|
||||
use _phone():
|
||||
style_prefix "phone_call"
|
||||
|
||||
screen phone_call(video=False):
|
||||
use _phone(xpos=gui.phone_call_xpos, xanchor=0.0):
|
||||
add Solid("#302D29")
|
||||
|
||||
vbox:
|
||||
text phone.calls._current_caller.name alt ""
|
||||
add DynamicDisplayable(phone.calls._call_time) alt ""
|
||||
if video and is_renpy_version_or_above(7, 6, 0): # _phone_video_call uses the `Layer` displayable
|
||||
use _phone_video_call()
|
||||
else:
|
||||
use _phone_call()
|
||||
|
||||
#if not phone.config.quick_menu and quick_menu:
|
||||
# use quick_menu()
|
||||
|
||||
frame:
|
||||
add phone.calls._current_caller.icon at _fits(None)
|
||||
screen _phone_call():
|
||||
style_prefix "phone_call"
|
||||
|
||||
if phone.config.quick_menu and quick_menu:
|
||||
vbox:
|
||||
text phone.short_name(phone.calls._current_caller.name, 12) alt ""
|
||||
add DynamicDisplayable(phone.calls._call_time) alt ""
|
||||
|
||||
frame:
|
||||
add phone.calls._current_caller.icon at _fits(None)
|
||||
|
||||
if phone.config.quick_menu and quick_menu:
|
||||
frame style "empty" xalign 0.5 ypos 0.45:
|
||||
use phone_quick_menu()
|
||||
|
||||
add phone.config.basedir + "hang_up.png":
|
||||
subpixel True zoom 0.35
|
||||
xalign 0.5 ypos 0.8
|
||||
|
||||
# if not phone.config.quick_menu and quick_menu:
|
||||
# use quick_menu()
|
||||
add phone.asset("hang_up.png"):
|
||||
subpixel True xysize (63, 63)
|
||||
xalign 0.5 ypos 0.8
|
||||
|
||||
style phone_call_vbox is empty:
|
||||
spacing 3
|
||||
@ -40,7 +47,7 @@ style phone_call_text is empty:
|
||||
outlines [ ]
|
||||
line_spacing 0
|
||||
size 24
|
||||
font phone.config.basedir + "Aller_Rg.ttf"
|
||||
font phone.asset("Aller_Rg.ttf")
|
||||
hyperlink_functions hyperlink_functions_style("phone_call_text_hyperlink")
|
||||
|
||||
style phone_call_text_hyperlink is phone_call_text:
|
||||
@ -54,4 +61,22 @@ style phone_call_frame is empty:
|
||||
xysize ( 120, 120) # :)
|
||||
padding (int(22 * (120 / 404)), int(22 * (120 / 404)))
|
||||
ypos 0.18
|
||||
xalign 0.5
|
||||
xalign 0.5
|
||||
|
||||
screen _phone_video_call():
|
||||
style_prefix "phone_video_call"
|
||||
|
||||
add Layer(phone.config.video_call_layer):
|
||||
at Transform(**phone.config.video_call_layer_transform_properties)
|
||||
|
||||
vbox:
|
||||
text _("Facetime - [phone.calls._current_caller.name!t]")
|
||||
add DynamicDisplayable(phone.calls._call_time)
|
||||
|
||||
use phone_quick_menu_video()
|
||||
|
||||
style phone_video_call_vbox is phone_call_vbox:
|
||||
ypos 0.03
|
||||
|
||||
style phone_video_call_text is phone_call_text:
|
||||
size 27
|
||||
|
@ -1,53 +1,50 @@
|
||||
screen phone_quick_menu():
|
||||
grid 3 2:
|
||||
style_prefix "phone_quick_menu"
|
||||
xalign 0.5 ypos 0.45
|
||||
|
||||
grid 3 2 style_prefix "phone_quick_menu":
|
||||
vbox:
|
||||
imagebutton:
|
||||
idle phone.config.basedir + "quick_menu_history_idle.png"
|
||||
hover phone.config.basedir + "quick_menu_history_selected.png"
|
||||
selected_idle phone.config.basedir + "quick_menu_history_selected.png"
|
||||
idle phone.asset("quick_menu_history_idle.png")
|
||||
hover phone.asset("quick_menu_history_selected.png")
|
||||
selected_idle phone.asset("quick_menu_history_selected.png")
|
||||
action ShowMenu("history")
|
||||
text _("History")
|
||||
|
||||
vbox:
|
||||
imagebutton:
|
||||
idle phone.config.basedir + "quick_menu_afm_idle.png"
|
||||
hover phone.config.basedir + "quick_menu_afm_selected.png"
|
||||
selected_idle phone.config.basedir + "quick_menu_afm_selected.png"
|
||||
idle phone.asset("quick_menu_afm_idle.png")
|
||||
hover phone.asset("quick_menu_afm_selected.png")
|
||||
selected_idle phone.asset("quick_menu_afm_selected.png")
|
||||
action Preference("auto-forward", "toggle")
|
||||
text _("Auto")
|
||||
|
||||
vbox:
|
||||
imagebutton:
|
||||
idle phone.config.basedir + "quick_menu_skip_idle.png"
|
||||
hover phone.config.basedir + "quick_menu_skip_selected.png"
|
||||
selected_idle phone.config.basedir + "quick_menu_skip_selected.png"
|
||||
idle phone.asset("quick_menu_skip_idle.png")
|
||||
hover phone.asset("quick_menu_skip_selected.png")
|
||||
selected_idle phone.asset("quick_menu_skip_selected.png")
|
||||
action Skip()
|
||||
text _("Skip")
|
||||
|
||||
vbox:
|
||||
imagebutton:
|
||||
idle phone.config.basedir + "quick_menu_settings_idle.png"
|
||||
hover phone.config.basedir + "quick_menu_settings_selected.png"
|
||||
selected_idle phone.config.basedir + "quick_menu_settings_selected.png"
|
||||
idle phone.asset("quick_menu_settings_idle.png")
|
||||
hover phone.asset("quick_menu_settings_selected.png")
|
||||
selected_idle phone.asset("quick_menu_settings_selected.png")
|
||||
action ShowMenu("preferences")
|
||||
text _("Settings")
|
||||
|
||||
vbox:
|
||||
imagebutton:
|
||||
idle phone.config.basedir + "quick_menu_save_idle.png"
|
||||
hover phone.config.basedir + "quick_menu_save_selected.png"
|
||||
selected_idle phone.config.basedir + "quick_menu_save_selected.png"
|
||||
idle phone.asset("quick_menu_save_idle.png")
|
||||
hover phone.asset("quick_menu_save_selected.png")
|
||||
selected_idle phone.asset("quick_menu_save_selected.png")
|
||||
action ShowMenu("save")
|
||||
text _("Save")
|
||||
|
||||
vbox:
|
||||
imagebutton:
|
||||
idle phone.config.basedir + "quick_menu_load_idle.png"
|
||||
hover phone.config.basedir + "quick_menu_load_selected.png"
|
||||
selected_idle phone.config.basedir + "quick_menu_load_selected.png"
|
||||
idle phone.asset("quick_menu_load_idle.png")
|
||||
hover phone.asset("quick_menu_load_selected.png")
|
||||
selected_idle phone.asset("quick_menu_load_selected.png")
|
||||
action ShowMenu("load")
|
||||
text _("Load")
|
||||
|
||||
@ -56,4 +53,47 @@ style phone_quick_menu_grid is empty:
|
||||
|
||||
style phone_quick_menu_vbox is empty
|
||||
style phone_quick_menu_text is phone_call_time:
|
||||
size 14
|
||||
size 14
|
||||
|
||||
screen phone_quick_menu_video():
|
||||
default qm = False
|
||||
default anim_time = 0.35
|
||||
|
||||
showif qm:
|
||||
add "#000":
|
||||
at transform:
|
||||
alpha 0.0
|
||||
on show:
|
||||
ease anim_time alpha 0.35
|
||||
on hide:
|
||||
ease anim_time alpha 0.0
|
||||
|
||||
vbox style "empty" yalign 1.0 xsize 1.0 xfill True:
|
||||
button style "empty" padding (5, 7, 5, 4) xalign 0.5:
|
||||
at transform:
|
||||
ease anim_time matrixtransform RotateMatrix(0, 0, 180 * qm) matrixcolor OpacityMatrix(0.8 if qm else 0.6)
|
||||
|
||||
action ToggleLocalVariable("qm")
|
||||
|
||||
add phone.asset("arrow_icon.png"):
|
||||
at transform:
|
||||
subpixel True xysize (70, 18)
|
||||
|
||||
showif qm:
|
||||
frame style "empty" top_padding 30 bottom_padding 15 xsize 1.0 modal True:
|
||||
at transform:
|
||||
subpixel True crop (0, 0, 1.0, 0.0)
|
||||
on show:
|
||||
ease anim_time crop (0, 0, 1.0, 1.0) alpha 1.0
|
||||
on hide:
|
||||
ease anim_time crop (0, 0, 1.0, 0.0) alpha 0.0
|
||||
|
||||
background "#00000060"
|
||||
|
||||
vbox style "empty" xalign 0.5:
|
||||
use phone_quick_menu()
|
||||
|
||||
null height 15
|
||||
|
||||
add phone.asset("hang_up.png"):
|
||||
subpixel True xysize (63, 63) xalign 0.5
|
||||
|
@ -30,8 +30,8 @@ style phone_say_dialogue is empty:
|
||||
ypos 0.0
|
||||
outlines [ ]
|
||||
color "#fff"
|
||||
font "gui/FallingSky.otf"
|
||||
font phone.asset("FallingSky.otf")
|
||||
|
||||
style phone_say_label is phone_say_dialogue:
|
||||
font phone.config.basedir + "JetBrainsMono-ExtraBold.ttf"
|
||||
font phone.asset("FallingSky.otf")
|
||||
size 27
|
@ -34,21 +34,20 @@ screen phone_contacts():
|
||||
PhoneMenu("phone_discussion")
|
||||
)
|
||||
|
||||
$ sender, message = group_chat._get_display_last_message()
|
||||
|
||||
hbox:
|
||||
add group_chat.icon at _fits(46) yalign 0.5
|
||||
|
||||
fixed:
|
||||
text message yalign 0.2:
|
||||
text phone.short_name(group_chat.name, 26) yalign 0.2:
|
||||
if group_chat.unread:
|
||||
color "#000"
|
||||
|
||||
text _("The [group_chat._date_text] at [group_chat._hour_text]"):
|
||||
style "phone_contacts_date_text" yalign 1.0
|
||||
|
||||
if sender is not None:
|
||||
text sender.short_name style "phone_contacts_date_text" align (1.0, 1.0)
|
||||
text (
|
||||
_("The [group_chat._date_text] at [group_chat._hour_text]")
|
||||
if group_chat.number_of_messages != 0
|
||||
else _("Empty group chat")
|
||||
):
|
||||
style "phone_contacts_date_text" yalign 1.0
|
||||
|
||||
style phone_contacts_side is empty:
|
||||
xfill True
|
||||
@ -74,7 +73,7 @@ style phone_contacts_text is empty:
|
||||
outlines [ ]
|
||||
color "#525252"
|
||||
size 18
|
||||
font phone.config.basedir + "Aller_Rg.ttf"
|
||||
font phone.asset("Aller_Rg.ttf")
|
||||
|
||||
style phone_contacts_no_friends is phone_contacts_text:
|
||||
color "#000"
|
||||
|
@ -31,20 +31,19 @@ init -100 python in phone.discussion:
|
||||
return
|
||||
else:
|
||||
raise Exception("group chat not given (no previous group chat was found)")
|
||||
|
||||
if _group_chat is not None:
|
||||
raise Exception("preparing group chat while another convesation is going on")
|
||||
|
||||
gc = group_chat(gc)
|
||||
|
||||
if not gc._characters:
|
||||
raise Exception("group chat '{}' has no characters".format(gc.name))
|
||||
|
||||
|
||||
_group_chat = gc
|
||||
_group_chat.unread = False
|
||||
|
||||
store._window_hide()
|
||||
|
||||
_yadjustment.value = float("inf")
|
||||
|
||||
set_current_screen("phone_discussion")
|
||||
show_layer_at([disc_blur])
|
||||
renpy.show_screen("phone_discussion")
|
||||
@ -53,23 +52,25 @@ init -100 python in phone.discussion:
|
||||
store._window_auto = True
|
||||
|
||||
def end_discussion():
|
||||
store._window_hide()
|
||||
|
||||
global _group_chat
|
||||
if _group_chat is None:
|
||||
raise Exception("ending discussion, but no discussion ever started")
|
||||
if _group_chat is None: return
|
||||
|
||||
store._window_hide()
|
||||
|
||||
for key in _group_chat._characters:
|
||||
sort_messages(key)
|
||||
if _group_chat.ephemeral:
|
||||
_group_chat.clear_payload()
|
||||
|
||||
if _group_chat.transient:
|
||||
_group_chat.clear()
|
||||
|
||||
_group_chat = None
|
||||
|
||||
show_layer_at([disc_unblur], reset=True)
|
||||
renpy.hide_screen("phone_discussion")
|
||||
renpy.with_statement(config.exit_transition)
|
||||
|
||||
set_current_screen(None)
|
||||
|
||||
|
||||
store._window_auto = True
|
||||
|
||||
class _Payload(object):
|
||||
@ -120,7 +121,6 @@ init -100 python in phone.discussion:
|
||||
if _group_chat._page == 0:
|
||||
_yadjustment.value = float("inf")
|
||||
|
||||
|
||||
_current_payload = None
|
||||
|
||||
if not no_pause:
|
||||
@ -144,7 +144,6 @@ init -100 python in phone.discussion:
|
||||
|
||||
dc.send(delay)
|
||||
|
||||
|
||||
def register_message(group, sender, text):
|
||||
_check_for_tags(text)
|
||||
|
||||
@ -299,6 +298,10 @@ init -100 python in phone.discussion:
|
||||
p = _Payload(sender.key, audio, AUDIO)
|
||||
group._save_payload(p)
|
||||
_run_callbacks(group, "save", p)
|
||||
|
||||
_yadjustment = ui.adjustment()
|
||||
|
||||
|
||||
|
||||
def add_history(sender,text):
|
||||
|
||||
@ -340,8 +343,6 @@ init -100 python in phone.discussion:
|
||||
|
||||
while len(history) > history_length:
|
||||
history.pop(0)
|
||||
|
||||
_yadjustment = ui.adjustment()
|
||||
|
||||
default -100 phone.discussion._current_payload = None
|
||||
default -100 phone.discussion._group_chat = None
|
||||
@ -374,7 +375,7 @@ init python in phone.discussion:
|
||||
from store.phone.character import character
|
||||
|
||||
init 1400 python in phone:
|
||||
@renpy.partial(_run_on_start, id="__sort_register_messages")
|
||||
@renpy.partial(execute_default, id="__sort_register_messages")
|
||||
def __sort_register_messages():
|
||||
global data
|
||||
for key in data:
|
||||
|
@ -1,13 +1,13 @@
|
||||
screen phone_discussion():
|
||||
key ["mouseup_1", "mouseup_3"] action Function(renpy.end_interaction, True) capture False
|
||||
use _phone():
|
||||
key ["mouseup_1", "mouseup_3", "K_UP"] action Function(renpy.end_interaction, True) capture True
|
||||
side "t b c":
|
||||
use app_base(action=(SetField(phone.discussion, "_group_chat", None), Function(phone.discussion.audio_messages.reset))):
|
||||
style_prefix "app_base"
|
||||
|
||||
hbox:
|
||||
add phone.discussion._group_chat.icon at _fits(36) yalign 0.5
|
||||
text phone.discussion._group_chat.short_name alt ""
|
||||
text phone.short_name(phone.discussion._group_chat.name, 9) alt ""
|
||||
|
||||
use _chat_textbox()
|
||||
use _chat_messages()
|
||||
@ -17,6 +17,7 @@ init -100 python in phone.discussion:
|
||||
class _AutoScrollVP(renpy.display.layout.Container):
|
||||
"""
|
||||
Actual dark magic...
|
||||
filtered, not even joking
|
||||
"""
|
||||
def __init__(self, vp):
|
||||
super(_AutoScrollVP, self).__init__(vp)
|
||||
@ -34,7 +35,6 @@ init -100 python in phone.discussion:
|
||||
adjusted_st, _ = self.adj_text.adjusted_times()
|
||||
|
||||
delta = min(1.0, adjusted_st / text_time)
|
||||
|
||||
# not really its size, but the width of what has been rendered
|
||||
# | |
|
||||
# | This is a super dup |
|
||||
@ -49,27 +49,31 @@ init -100 python in phone.discussion:
|
||||
return super(_AutoScrollVP, self).render(w, h, st, at)
|
||||
|
||||
screen _chat_textbox():
|
||||
|
||||
style_prefix "phone_textbox"
|
||||
frame: # ugly double framing but whatever, we're rolling with it otherwise it make the entire phone stretch outwards.
|
||||
top_margin 10 # Part of the revised phone ui. Needed to avoid clipping
|
||||
hbox:
|
||||
frame:
|
||||
style "phone_text_inputbox"
|
||||
if phone.discussion._current_payload is not None and phone.discussion._current_payload.source is not None:
|
||||
$ sender = phone.character.character(phone.discussion._current_payload.source)
|
||||
if (
|
||||
sender.is_pov and
|
||||
phone.discussion._current_payload.type == phone.discussion._PayloadTypes.TEXT
|
||||
):
|
||||
fixed style "empty":
|
||||
yfill True
|
||||
xsize 0.9
|
||||
|
||||
frame:
|
||||
side "l r":
|
||||
if phone.discussion._current_payload is not None and phone.discussion._current_payload.source is not None:
|
||||
$ sender = phone.character.character(phone.discussion._current_payload.source)
|
||||
if (
|
||||
sender.is_pov and
|
||||
phone.discussion._current_payload.type == phone.discussion._PayloadTypes.TEXT
|
||||
):
|
||||
fixed style "empty":
|
||||
yfill True
|
||||
xsize 0.9
|
||||
viewport at phone.discussion._AutoScrollVP style "empty":
|
||||
draggable False
|
||||
mousewheel False
|
||||
yalign 0.5
|
||||
xoffset 11 #don't add it to Text()
|
||||
|
||||
viewport at phone.discussion._AutoScrollVP style "empty":
|
||||
draggable False
|
||||
mousewheel False
|
||||
yalign 0.5
|
||||
|
||||
frame style "phone_textbox_typing_text_frame":
|
||||
add renpy.display.layout.AdjustTimes(
|
||||
frame style "phone_textbox_typing_text_frame":
|
||||
add renpy.display.layout.AdjustTimes(
|
||||
Text(
|
||||
" " + __(phone.discussion._current_payload.data),
|
||||
style="phone_textbox_text",
|
||||
@ -78,18 +82,33 @@ screen _chat_textbox():
|
||||
None,
|
||||
None
|
||||
)
|
||||
else:
|
||||
text _("Type a message.") color "#666" alt "" xoffset 11
|
||||
# ugly ahh
|
||||
# to the genius who tried removing the top conditional, no, the phone creator did this hack for a reason
|
||||
# you gargoyle
|
||||
else:
|
||||
text _(" Type a message.") color "#666" alt ""
|
||||
# ugly ahh
|
||||
else:
|
||||
text _(" Type a message.") color "#666" alt ""
|
||||
text _("Type a message.") color "#666" alt "" xoffset 11
|
||||
|
||||
text _("Send ") color "#0094FF" xalign 1.0 alt ""
|
||||
|
||||
frame:
|
||||
style "phone_text_sendbutton"
|
||||
text _("Send") color "#0094FF" xalign 0.0 alt ""
|
||||
|
||||
|
||||
style phone_text_inputbox is empty:
|
||||
ysize 52 xsize 0.875
|
||||
padding (10, 5, 0)
|
||||
background RoundedCorners(Solid("#F2F2F2"), radius=phone.config.textbox_radius, outline_width=2.0, outline_color="#9b9b9b")
|
||||
|
||||
style phone_text_sendbutton is empty:
|
||||
padding (8, 10, 0)
|
||||
ysize 50
|
||||
|
||||
style phone_textbox_frame is empty:
|
||||
ysize 50 xfill True
|
||||
background "#F2F2F2"
|
||||
xsize 0.94
|
||||
xoffset 12
|
||||
yoffset -20
|
||||
padding (10, 10)
|
||||
|
||||
style phone_textbox_side is empty:
|
||||
@ -98,11 +117,11 @@ style phone_textbox_side is empty:
|
||||
|
||||
style phone_textbox_text is empty:
|
||||
outlines [ ]
|
||||
size 16
|
||||
size 22 #unbearable to read at 18
|
||||
color "#000"
|
||||
line_leading 0
|
||||
line_spacing 0
|
||||
font phone.config.basedir + "Aller_Rg.ttf"
|
||||
font phone.asset("Aller_Rg.ttf")
|
||||
yalign 0.5
|
||||
layout "nobreak"
|
||||
|
||||
@ -110,6 +129,8 @@ style phone_textbox_typing_text_frame is empty:
|
||||
yfill True
|
||||
|
||||
|
||||
|
||||
|
||||
screen _chat_message(p):
|
||||
style_prefix "phone_messages"
|
||||
|
||||
@ -140,6 +161,7 @@ screen _chat_messages():
|
||||
|
||||
viewport style "empty" at Flatten:
|
||||
yadjustment phone.discussion._yadjustment
|
||||
ymaximum 715 # Part of the revised phone ui. Needed to make room for the margin property in the textbox.
|
||||
draggable True
|
||||
mousewheel True
|
||||
yinitial 1.0
|
||||
@ -148,7 +170,7 @@ screen _chat_messages():
|
||||
|
||||
frame style "empty":
|
||||
yalign 1.0
|
||||
padding (10, 10)
|
||||
padding (10, 20, 10, 40)
|
||||
|
||||
vbox:
|
||||
if phone.discussion._group_chat._can_load_more():
|
||||
@ -156,7 +178,6 @@ screen _chat_messages():
|
||||
action (
|
||||
Function(phone.discussion._group_chat._page_up),
|
||||
SetField(phone.discussion._yadjustment, "value", float("inf")),
|
||||
SetLocalVariable("_label", False),
|
||||
Function(phone.discussion.audio_messages.reset)
|
||||
)
|
||||
bottom_margin 5
|
||||
@ -169,13 +190,12 @@ screen _chat_messages():
|
||||
null height gui.phone_message_label_null_height
|
||||
|
||||
text p.data style "phone_messages_text_label"
|
||||
|
||||
else:
|
||||
if _label:
|
||||
$ _label = False
|
||||
null height gui.phone_message_label_null_height
|
||||
|
||||
if p.type == phone.discussion._PayloadTypes.TEXT:
|
||||
if p.type == phone.discussion._PayloadTypes.TEXT:
|
||||
use _chat_message(p):
|
||||
if i != phone.discussion._group_chat.number_of_messages-1 or renpy.get_screen("say"):
|
||||
text p.data alt ""
|
||||
@ -184,7 +204,6 @@ screen _chat_messages():
|
||||
text p.data alt sender + ": " + p.data
|
||||
# $print(dir(phone.discussion._group_chat))
|
||||
|
||||
|
||||
elif p.type == phone.discussion._PayloadTypes.IMAGE:
|
||||
use _chat_message(p):
|
||||
imagebutton:
|
||||
@ -193,7 +212,7 @@ screen _chat_messages():
|
||||
fit "scale-down"
|
||||
|
||||
idle p.data
|
||||
action Show("_phone_image", dissolve, img=p.data)
|
||||
action Show("_phone_image", Dissolve(0.5), img=p.data)
|
||||
|
||||
elif p.type == phone.discussion._PayloadTypes.AUDIO:
|
||||
use _chat_message(p):
|
||||
@ -202,7 +221,7 @@ screen _chat_messages():
|
||||
add DynamicDisplayable(phone.discussion.audio_messages.button_image, p=p)
|
||||
action Function(phone.discussion.audio_messages.play_audio, p, p.data),
|
||||
|
||||
add phone.config.basedir + "audio_message_wave_icon.png":
|
||||
add phone.asset("audio_message_wave_icon.png"):
|
||||
at _fits(None), phone.discussion.audio_messages.AudioWave(p)
|
||||
|
||||
else:
|
||||
@ -214,15 +233,17 @@ screen _chat_messages():
|
||||
if _label:
|
||||
$ _label = False
|
||||
null height gui.phone_message_label_null_height
|
||||
|
||||
|
||||
for i, caption in enumerate(phone.discussion._current_payload.data):
|
||||
textbutton caption:
|
||||
style_prefix "phone_messages_choice"
|
||||
action Return(caption)
|
||||
at transform:
|
||||
frame style "empty":
|
||||
at transform: # support for versions that can't have `at` and `at transform` at the same time
|
||||
subpixel True alpha 0.0 xoffset -20 xalign 1.0
|
||||
i / 9
|
||||
ease_quad 0.35 alpha 1.0 xoffset 0
|
||||
|
||||
textbutton caption at CurriedRoundedCorners(radius=phone.config.textbox_radius):
|
||||
style_prefix "phone_messages_choice"
|
||||
action Return(caption)
|
||||
|
||||
else:
|
||||
$ sender = phone.character.character(phone.discussion._current_payload.source)
|
||||
@ -234,7 +255,6 @@ screen _chat_messages():
|
||||
if phone.discussion._current_payload.type == phone.discussion._PayloadTypes.IMAGE:
|
||||
use _chat_message(phone.discussion._current_payload):
|
||||
text _("{u}{i}Loading Image...{i}{/u}")
|
||||
|
||||
elif phone.discussion._current_payload.type == phone.discussion._PayloadTypes.AUDIO:
|
||||
use _chat_message(phone.discussion._current_payload):
|
||||
text _("{u}{i}Loading Audio...{i}{/u}")
|
||||
@ -243,19 +263,17 @@ screen _chat_messages():
|
||||
use _chat_message(phone.discussion._current_payload):
|
||||
text _("{u}{i}Loading Video...{i}{/u}")
|
||||
|
||||
else:
|
||||
else:
|
||||
if _label:
|
||||
$ _label = False
|
||||
null height gui.phone_message_label_null_height
|
||||
|
||||
use _phone_message_typing(sender)
|
||||
|
||||
if phone.discussion._group_chat._page > 0:
|
||||
textbutton _("Go Back"):
|
||||
action (
|
||||
Function(phone.discussion._group_chat._page_down),
|
||||
SetField(phone.discussion._yadjustment, "value", 0.0),
|
||||
SetLocalVariable("_label", False),
|
||||
Function(phone.discussion.audio_messages.reset)
|
||||
)
|
||||
top_margin 5
|
||||
@ -267,7 +285,7 @@ screen _phone_image(img):
|
||||
add img:
|
||||
align (0.5, 0.5)
|
||||
|
||||
key ["mouseup_1", "mouseup_3"] action Hide("_phone_image", dissolve)
|
||||
key ["mouseup_1", "mouseup_3"] action Hide("_phone_image", Dissolve(0.5))
|
||||
|
||||
style phone_messages_button is empty:
|
||||
xalign 0.5
|
||||
@ -276,24 +294,24 @@ style phone_messages_button_text is phone_say_dialogue:
|
||||
xalign 0.5
|
||||
text_align 0.5
|
||||
ypos 0.0
|
||||
size 16
|
||||
size 22
|
||||
color "#000"
|
||||
|
||||
style phone_messages_vbox is empty:
|
||||
spacing 5
|
||||
yalign 1.0
|
||||
xfill True
|
||||
xfill True
|
||||
|
||||
style phone_messages_hbox is empty:
|
||||
spacing 5
|
||||
|
||||
style phone_messages_text is empty:
|
||||
outlines [ ]
|
||||
size 22
|
||||
size 24
|
||||
line_leading 0
|
||||
line_spacing 0
|
||||
layout "greedy"
|
||||
font phone.config.basedir + "Aller_Rg.ttf"
|
||||
font phone.asset("Aller_Rg.ttf")
|
||||
hyperlink_functions hyperlink_functions_style("phone_messages_text_hyperlink")
|
||||
|
||||
style phone_messages_text is empty:
|
||||
@ -310,19 +328,19 @@ style phone_messages_frame is empty:
|
||||
style phone_messages_text_label is phone_messages_text:
|
||||
color "#000"
|
||||
xalign 0.5 text_align 0.5
|
||||
size 15
|
||||
size 20
|
||||
xsize 0.8
|
||||
|
||||
style phone_messages_choice_button is phone_messages_frame:
|
||||
background RoundedFrame(Solid("#eeeeee"), radius=phone.config.textbox_radius, outline_width=2.0, outline_color="#9b9b9b")
|
||||
hover_background RoundedFrame(Solid("#b4b4b4"), radius=phone.config.textbox_radius, outline_width=2.0, outline_color="#4d4d4d")
|
||||
background "#eeeeee"
|
||||
hover_background "#b4b4b4"
|
||||
padding (12, 8)
|
||||
|
||||
style phone_messages_choice_button_text is phone_messages_text:
|
||||
color "#000"
|
||||
outlines [ ]
|
||||
yalign 0.5
|
||||
size 18
|
||||
size 22
|
||||
layout "tex"
|
||||
|
||||
style phone_messages_audio_hbox is empty:
|
||||
|
@ -1,28 +1,23 @@
|
||||
init -100 python in phone.group_chat:
|
||||
from renpy import store
|
||||
from store import __, phone
|
||||
from renpy.store import store, phone
|
||||
import datetime
|
||||
|
||||
# The max lenght of a *group chat*'s name shortened.
|
||||
short_name_length = 9
|
||||
|
||||
# How many messages we display at the same time.
|
||||
messages_displayed = 175
|
||||
|
||||
# If the next "load" of messages contains this many or less messages, add those messages to the current load.
|
||||
messages_fill_if_lower = 15
|
||||
config = phone.config
|
||||
|
||||
class GroupChat(object):
|
||||
def __init__(self, name, icon, key, ephemeral=False):
|
||||
transient = False
|
||||
_unread = True
|
||||
|
||||
def __init__(self, name, icon, key, transient=False):
|
||||
global _group_chats
|
||||
_group_chats[key] = self
|
||||
|
||||
self.name = name
|
||||
self.icon = icon
|
||||
self.date = datetime.datetime(year=1970, month=1, day=1, hour=0, minute=0)
|
||||
self.ephemeral = ephemeral
|
||||
self.transient = transient
|
||||
|
||||
self.unread = True
|
||||
self._unread = True
|
||||
|
||||
self._characters = set()
|
||||
self._payloads = [ ]
|
||||
@ -30,16 +25,23 @@ init -100 python in phone.group_chat:
|
||||
|
||||
if key is None: raise ValueError("key may not be 'None'")
|
||||
self.key = key
|
||||
|
||||
# deprecated
|
||||
self.short_name = name
|
||||
|
||||
@property
|
||||
def short_name(self):
|
||||
global short_name_length
|
||||
name = __(self.name)
|
||||
if len(name) > short_name_length:
|
||||
name = name[:short_name_length - 3] + "..."
|
||||
|
||||
return name
|
||||
def unread(self):
|
||||
if not config.unread_group_chat_pov:
|
||||
return self._unread
|
||||
return phone.data[store.pov_key]["group_chat_unread_pov"].setdefault(self.key, True)
|
||||
|
||||
@unread.setter
|
||||
def unread(self, v):
|
||||
if not config.unread_group_chat_pov:
|
||||
self._unread = v
|
||||
else:
|
||||
phone.data[store.pov_key]["group_chat_unread_pov"][self.key] = v
|
||||
|
||||
def add_character(self, char):
|
||||
if isinstance(char, list):
|
||||
for c in char:
|
||||
@ -74,67 +76,27 @@ init -100 python in phone.group_chat:
|
||||
@property
|
||||
def number_of_messages(self):
|
||||
return self.number_of_messages_sent(None)
|
||||
|
||||
def clear(self):
|
||||
self._payloads.clear()
|
||||
|
||||
def _can_load_more(self):
|
||||
if not self._payloads: return False
|
||||
return next(self._get_messages()) is not self._payloads[0]
|
||||
|
||||
def _get_display_last_message(self):
|
||||
italic = True
|
||||
|
||||
if not self._payloads:
|
||||
sender = None
|
||||
message = __("Empty group chat")
|
||||
|
||||
else:
|
||||
p = self._payloads[-1]
|
||||
|
||||
sender = p.source
|
||||
if sender is not None: sender = character(sender)
|
||||
|
||||
_type = p.type
|
||||
|
||||
if _type == _PayloadTypes.TEXT:
|
||||
message = renpy.substitute(p.data)
|
||||
italic = False
|
||||
|
||||
elif _type == _PayloadTypes.IMAGE:
|
||||
message = __("Image sent")
|
||||
|
||||
elif _type == _PayloadTypes.LABEL:
|
||||
message = renpy.substitute(p.data)
|
||||
|
||||
elif _type == _PayloadTypes.DATE:
|
||||
message = p.data
|
||||
|
||||
elif _type == _PayloadTypes.AUDIO:
|
||||
message = __("Audio sent")
|
||||
|
||||
elif _type == _PayloadTypes.VIDEO:
|
||||
message = __("Video sent")
|
||||
|
||||
message = remove_text_tags(message)
|
||||
|
||||
LIMIT = 27
|
||||
if len(message) >= LIMIT:
|
||||
message = message[:LIMIT - 3] + "..."
|
||||
|
||||
if italic:
|
||||
message = "{i}" + message + "{/i}"
|
||||
|
||||
return (sender, message)
|
||||
return self._get_messages()[0] is not self._payloads[0]
|
||||
|
||||
def _get_messages(self):
|
||||
global messages_displayed
|
||||
messages_displayed = config.messages_displayed
|
||||
|
||||
min_x = self._page * messages_displayed
|
||||
max_x = min_x + messages_displayed
|
||||
|
||||
global messages_fill_if_lower
|
||||
remaining = len(self._payloads) - max_x
|
||||
if remaining <= messages_fill_if_lower:
|
||||
l = len(self._payloads)
|
||||
|
||||
remaining = l - max_x
|
||||
if remaining <= config.messages_fill_if_lower:
|
||||
max_x += remaining
|
||||
|
||||
return reversed(self._payloads[::-1][min_x:max_x])
|
||||
return self._payloads[l-max_x:l-min_x]
|
||||
|
||||
@property
|
||||
def _date_text(self):
|
||||
@ -171,9 +133,6 @@ init -100 python in phone.group_chat:
|
||||
def __len__(self):
|
||||
return len(self._payloads)
|
||||
|
||||
def clear_payload(self):
|
||||
self._payloads=[]
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.key)
|
||||
|
||||
|
@ -19,7 +19,7 @@ screen _phone_message_typing(sender):
|
||||
text "⚫" at _phone_message_typing(0.2) alt ""
|
||||
text "⚫" at _phone_message_typing(0.4) alt ""
|
||||
|
||||
text _("[sender.short_name!t] is typing...") style "phone_typing_istyping" yalign 0.5 alt ""
|
||||
text __("{short_name} is typing...").format(short_name=phone.short_name(sender.name, 9)) style "phone_typing_istyping" yalign 0.5 alt ""
|
||||
|
||||
style phone_typing_hbox is empty:
|
||||
spacing 3
|
||||
@ -34,5 +34,9 @@ style phone_typing_text is phone_messages_text:
|
||||
style phone_typing_istyping is empty:
|
||||
color "#626262"
|
||||
outlines [ ]
|
||||
size 16
|
||||
font phone.config.basedir + "Aller_Rg.ttf"
|
||||
size 22
|
||||
font phone.asset("Aller_Rg.ttf")
|
||||
|
||||
init python:
|
||||
if is_renpy_version_or_above(7, 7, 0):
|
||||
style.phone_typing_text.emoji_font = None
|
||||
|
@ -1,17 +1,9 @@
|
||||
init -100 python in phone.character:
|
||||
from renpy import store
|
||||
from store import Color, __, RoundedFrame
|
||||
from renpy.store import store, Color, __, RoundedCorners, phone
|
||||
from store.phone import config
|
||||
|
||||
# The max lenght of a *character*'s name shortened.
|
||||
character_short_name_length = 16
|
||||
|
||||
# A number of seconds added to the pause before each message.
|
||||
message_delay = 0.6
|
||||
|
||||
class Character(object):
|
||||
def __init__(self, name, icon, key, cps, color):
|
||||
global _characters
|
||||
_characters[key] = self
|
||||
|
||||
self.name = name
|
||||
@ -23,26 +15,19 @@ init -100 python in phone.character:
|
||||
if key is None: raise ValueError("key may not be 'None'")
|
||||
self.key = key
|
||||
|
||||
# deprecated
|
||||
self.short_name = name
|
||||
|
||||
def get_textbox(self):
|
||||
return get_textbox(self.color)
|
||||
|
||||
@property
|
||||
def short_name(self):
|
||||
global character_short_name_length
|
||||
name = __(self.name)
|
||||
if len(name) > character_short_name_length:
|
||||
name = name[:character_short_name_length - 3] + "..."
|
||||
|
||||
return name
|
||||
|
||||
@property
|
||||
def is_pov(self):
|
||||
return self.key == store.pov_key
|
||||
|
||||
def get_typing_delay(self, message, substitute=True):
|
||||
global message_delay
|
||||
if substitute: message = renpy.substitute(message)
|
||||
return (len(message) / self.cps) + message_delay
|
||||
def get_typing_delay(self, message, substitute=True, translate=True):
|
||||
if substitute: message = renpy.substitute(message, translate=translate)
|
||||
return (len(message) / self.cps) + config.message_delay
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.key)
|
||||
@ -51,14 +36,14 @@ init -100 python in phone.character:
|
||||
if isinstance(x, Character): return x
|
||||
if x is None: x = store.pov_key
|
||||
if not has_character(x):
|
||||
raise KeyError("nno phone Character with the key %r exists (check your definitions)" % x)
|
||||
raise KeyError("no phone Character with the key %r exists (check your definitions)" % x)
|
||||
return _characters[x]
|
||||
|
||||
def has_character(key):
|
||||
return key in _characters
|
||||
|
||||
def get_textbox(color):
|
||||
return RoundedFrame(color, radius=config.textbox_radius)
|
||||
return RoundedCorners(color, radius=config.textbox_radius)
|
||||
|
||||
def get_all():
|
||||
return list(_characters.values())
|
||||
|
@ -5,8 +5,7 @@ init -100 python in phone.discussion:
|
||||
config.enter_transition = easeinbottom
|
||||
|
||||
python early in phone.config:
|
||||
from renpy import store
|
||||
from store import Dissolve, _warper, _, phone, Transform
|
||||
from renpy.store import store, config as renpy_config, Dissolve, _warper, _, phone, Transform
|
||||
_constant = True
|
||||
|
||||
# Where the assets are located.
|
||||
@ -55,8 +54,14 @@ python early in phone.config:
|
||||
# A dictionary mapping screen names to transforms or lists of transforms.
|
||||
# When a phone screen is shown, the screen name is looked up in the map (None is used if not found),
|
||||
# and the layer "master" is shown at those transforms.
|
||||
layer_at_transforms = { }
|
||||
# `None` is set later
|
||||
layer_at_transforms = {
|
||||
None: Transform(matrixcolor=renpy.display.matrix.Matrix([1, 0, 0, -0.03, # BrightnessMatrix(-0.03)
|
||||
0, 1, 0, -0.03,
|
||||
0, 0, 1, -0.03,
|
||||
0, 0, 0, 1]),
|
||||
blur=2
|
||||
)
|
||||
}
|
||||
|
||||
# How many "pages" of application we use in the `phone` screen.
|
||||
applications_pages = 4
|
||||
@ -70,6 +75,7 @@ python early in phone.config:
|
||||
"group_chats": list,
|
||||
"background_image": lambda: None,
|
||||
"calendars": list,
|
||||
"group_chat_unread_pov": dict
|
||||
}
|
||||
|
||||
def _generate_applications_dict():
|
||||
@ -108,6 +114,51 @@ python early in phone.config:
|
||||
# -For a video, `None`.
|
||||
discussion_callbacks = [ ]
|
||||
|
||||
init -1400 python in phone.config:
|
||||
from store import BrightnessMatrix
|
||||
layer_at_transforms[None] = None
|
||||
# The name of the layer usied in video calls. It is appended to `config.detached_layers`
|
||||
video_call_layer = "phone_video_call"
|
||||
|
||||
# A dict of transform properties applied to the `Layer` displayable used during a video call.
|
||||
video_call_layer_transform_properties = {
|
||||
"align": (0.5, 1.0),
|
||||
"ysize": 1.0,
|
||||
"fit": "contain"
|
||||
}
|
||||
|
||||
# How many messages we display at the same time.
|
||||
messages_displayed = 175
|
||||
|
||||
# If the next "load" of messages contains this many or less messages, add those messages to the current load.
|
||||
messages_fill_if_lower = 15
|
||||
|
||||
# A number of seconds added to the pause before each message.
|
||||
message_delay = 0.6
|
||||
|
||||
# An index. The default calendar used when the `phone_calendars` screen is shown.
|
||||
# If `True`, tries to retrieve the calendar that's in concordance to `phone.system.get_date()`.
|
||||
default_calendar_index = -1
|
||||
|
||||
# If true, a group chat's "unreadness" is determined on the pov the group chat was read in.
|
||||
# I.e, if the group chat was read in the "mc" pov, then it won't be marked as read in the "s" pov.
|
||||
# If false, it is determined by whether the player has opened the group chat or not.
|
||||
unread_group_chat_pov = False
|
||||
|
||||
# If true, will define all images found in "assets/emojis" as emojis.
|
||||
auto_emojis = True
|
||||
|
||||
# The default value of the `delay` property for the `time` and `label` discussion statements.
|
||||
default_label_delay = 0.5
|
||||
|
||||
python early: # prevent "default"
|
||||
config.special_namespaces["store.phone.config"] = type(config.special_namespaces["store.config"])(phone.config, "phone.config")
|
||||
|
||||
init 1500 python in phone:
|
||||
@renpy_config.after_load_callbacks.append
|
||||
def __ensure_phone_data_entries():
|
||||
changed = False
|
||||
for d in data.values():
|
||||
for thing, f in config.data.items():
|
||||
if thing not in d:
|
||||
d[thing] = f()
|
||||
changed = True
|
||||
if changed:
|
||||
renpy.block_rollback()
|
||||
|
@ -1,16 +1,15 @@
|
||||
default pc_damien = phone.character.Character("D-Man", phone.asset("damien_icon.png"), "D", 24, "#22Abf8")
|
||||
default pc_olivia = phone.character.Character("Liv-Long", phone.asset("olivia_icon.png"), "O", 40, "#22Abf8")
|
||||
default pc_sophia = phone.character.Character("Ms.P", phone.asset("sophia_icon.png"), "S", 20, "#22Abf8")
|
||||
default pc_liz = phone.character.Character("Liz", phone.asset("liz_icon.png"), "L", 35, "#484848")
|
||||
default pc_inco = phone.character.Character("Inco", phone.asset("inco_icon.png"), "I", 35, "#484848")
|
||||
|
||||
default pov_key = "I"
|
||||
|
||||
default pc_damien = phone.character.Character("D-Man", phone.config.basedir + "damien_icon.png", "D", 24, "#22Abf8")
|
||||
default pc_olivia = phone.character.Character("Liv-Long", phone.config.basedir + "olivia_icon.png", "O", 40, "#22Abf8")
|
||||
default pc_sophia = phone.character.Character("Ms.P", phone.config.basedir + "sophia_icon.png", "S", 20, "#22Abf8")
|
||||
default pc_liz = phone.character.Character("Liz", phone.config.basedir + "liz_icon.png", "L", 35, "#484848")
|
||||
default pc_inco = phone.character.Character("Inco", phone.config.basedir + "inco_icon.png", "I", 35, "#484848")
|
||||
|
||||
|
||||
default damien_chat = phone.group_chat.GroupChat("D-Man", phone.config.basedir + "damien_icon.png", "damien_chat", ephemeral=True).add_character("D").add_character("I")
|
||||
default livia_chat = phone.group_chat.GroupChat("Liv-Long", phone.config.basedir + "olivia_icon.png", "olivia_chat", ephemeral=True).add_character("O").add_character("I")
|
||||
default sophia_chat = phone.group_chat.GroupChat("Ms.P", phone.config.basedir + "sophia_icon.png", "sophia_chat").add_character("S").add_character("I") # We don't care about if her chat gets cleared or not
|
||||
default liz_chat = phone.group_chat.GroupChat("Liz", phone.config.basedir + "liz_icon.png", "liz_chat", ephemeral=True).add_character("L").add_character("I")
|
||||
default damien_chat = phone.group_chat.GroupChat("D-Man", phone.asset("damien_icon.png"), "damien_chat", transient=True).add_character("D").add_character("I")
|
||||
default livia_chat = phone.group_chat.GroupChat("Liv-Long", phone.asset("olivia_icon.png"), "olivia_chat", transient=True).add_character("O").add_character("I")
|
||||
default sophia_chat = phone.group_chat.GroupChat("Ms.P", phone.asset("sophia_icon.png"), "sophia_chat").add_character("S").add_character("I") # We don't care about if her chat gets cleared or not
|
||||
default liz_chat = phone.group_chat.GroupChat("Liz", phone.asset("liz_icon.png"), "liz_chat", transient=True).add_character("L").add_character("I")
|
||||
|
||||
define EMOJI_PATH = "/gui/phone_assets/emojis/"
|
||||
|
||||
@ -61,3 +60,6 @@ init 100 python in phone.application:
|
||||
add_app_to_all_characters(message_app)
|
||||
add_app_to_all_characters(call_history_app)
|
||||
add_app_to_all_characters(calendar_app)
|
||||
|
||||
init 100 python in phone.calendar:
|
||||
add_calendar_to_all_characters(2023, 6, MONDAY)
|
||||
|
@ -1,7 +1,7 @@
|
||||
init -150 python in phone.emojis:
|
||||
from renpy import store
|
||||
from store import Transform
|
||||
from renpy.store import store, Transform, phone
|
||||
from store.phone import config
|
||||
_constant = True
|
||||
|
||||
import string
|
||||
_NOT_ALLOWED_CHARACTERS = set(string.punctuation.strip("_") + " ")
|
||||
@ -15,16 +15,13 @@ init -150 python in phone.emojis:
|
||||
|
||||
global _emojis
|
||||
_emojis[name] = renpy.displayable(emoji)
|
||||
|
||||
add("clueless", config.basedir + "emojis/clueless.png")
|
||||
add("randomguy", config.basedir + "emojis/randomguy.png")
|
||||
|
||||
|
||||
def get(name):
|
||||
return _emojis[name]
|
||||
|
||||
def _emoji_tag(tag, name):
|
||||
return [
|
||||
(renpy.TEXT_DISPLAYABLE, Transform(get(name), subpixel=True, ysize=1.0, fit="contain", yoffset=2))
|
||||
(renpy.TEXT_DISPLAYABLE, Transform(get(name), subpixel=True, ysize=1.0, fit="contain"))
|
||||
]
|
||||
|
||||
store.config.self_closing_custom_text_tags["emoji"] = _emoji_tag
|
||||
@ -34,4 +31,32 @@ init -150 python in phone.emojis:
|
||||
|
||||
def format_emoji_tag(s):
|
||||
for emoji in _tag_pattern.findall(s): s = _tag_pattern.sub(":" + emoji + ":", s, 1)
|
||||
return s
|
||||
return s
|
||||
|
||||
init 1000 python hide in phone.emojis:
|
||||
if config.auto_emojis:
|
||||
import os
|
||||
|
||||
emoji_base_path = phone.asset("emojis")
|
||||
|
||||
try:
|
||||
for emoji in os.listdir(phone.path_join(store.config.basedir, "game", emoji_base_path)):
|
||||
stuff = emoji.split(".")
|
||||
|
||||
if len(stuff) != 2: continue
|
||||
name, extension = stuff
|
||||
|
||||
if extension.lower() not in ("png", "jpg", "jpeg", "svg"):
|
||||
continue
|
||||
|
||||
add(name, phone.path_join(emoji_base_path, emoji))
|
||||
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
# prevent `default`
|
||||
python early in phone.emojis:
|
||||
pass
|
||||
|
||||
python early:
|
||||
config.special_namespaces["store.phone.emojis"] = type(config.special_namespaces["store.config"])(phone.emojis, "phone.emojis")
|
||||
|
@ -8,7 +8,7 @@ screen _phone_click_effects():
|
||||
|
||||
define phone_click_uptime = 0.3
|
||||
image phone_click_effect:
|
||||
phone.config.basedir + "circle.png"
|
||||
phone.asset("circle.png")
|
||||
alpha 0.34 matrixcolor TintMatrix("#464646")
|
||||
subpixel True xysize (25, 25)
|
||||
easein (phone_click_uptime * 0.4) xysize (50, 50) alpha 0.7
|
||||
@ -17,7 +17,7 @@ define phone_on_click_effect = ("phone_click_effect", phone_click_uptime)
|
||||
|
||||
define phone_drag_uptime = 0.4
|
||||
image phone_drag_effect:
|
||||
phone.config.basedir + "circle.png"
|
||||
phone.asset("circle.png")
|
||||
alpha 0.17 matrixcolor TintMatrix("#464646")
|
||||
subpixel True xysize (20, 20)
|
||||
easeout phone_drag_uptime alpha 0.0 xysize (0, 0)
|
||||
|
@ -10,6 +10,7 @@ init -100 python in phone.status_bar:
|
||||
def battery_text_displayable(st, at):
|
||||
return Text("{}%".format(system.get_battery_level()), style="_phone_status_bar_text"), 0.1
|
||||
|
||||
EMPTY = 0
|
||||
ONE_FOURTH = 1
|
||||
HALF = 2
|
||||
THREE_FOURTH = 3
|
||||
@ -17,6 +18,7 @@ init -100 python in phone.status_bar:
|
||||
FULL = 5
|
||||
|
||||
_battery_displayables = {
|
||||
EMPTY: renpy.displayable(config.basedir + "status_bar_battery_empty.png"),
|
||||
ONE_FOURTH: renpy.displayable(config.basedir + "status_bar_battery_one_fourth.png"),
|
||||
HALF: renpy.displayable(config.basedir + "status_bar_battery_half.png"),
|
||||
THREE_FOURTH: renpy.displayable(config.basedir + "status_bar_battery_three_fourth.png"),
|
||||
@ -29,6 +31,9 @@ init -100 python in phone.status_bar:
|
||||
|
||||
REDRAW = 0.5
|
||||
|
||||
if battery_level == 0:
|
||||
return _battery_displayables[EMPTY], REDRAW
|
||||
|
||||
if battery_level <= 33: # bamboozled
|
||||
return _battery_displayables[ONE_FOURTH], REDRAW
|
||||
|
||||
@ -90,12 +95,9 @@ screen _phone_status_bar():
|
||||
add DynamicDisplayable(phone.status_bar.battery_text_displayable)
|
||||
add DynamicDisplayable(phone.status_bar.battery_displayable) at _fits(0.74) yalign 0.5
|
||||
|
||||
action SetLocalVariable("control_center", True)
|
||||
action (SetLocalVariable("control_center", True), SetField(phone.system, "at_list", _phone_control_center))
|
||||
|
||||
else:
|
||||
on "show" action SetField(phone.system, "at_list", _phone_control_center)
|
||||
on "hide" action SetField(phone.system, "at_list", _phone_status_bar)
|
||||
|
||||
add "#c4c4c438":
|
||||
at transform:
|
||||
on show:
|
||||
@ -117,7 +119,7 @@ screen _phone_status_bar():
|
||||
frame style "empty" modal True:
|
||||
button:
|
||||
style "empty" xfill True yfill True
|
||||
action SetLocalVariable("control_center", False)
|
||||
action (SetLocalVariable("control_center", False), SetField(phone.system, "at_list", _phone_status_bar))
|
||||
|
||||
hbox at Flatten:
|
||||
xalign 0.5 yanchor 1.0 ypos 0.98
|
||||
@ -125,7 +127,7 @@ screen _phone_status_bar():
|
||||
vbox:
|
||||
use _phone_control_center_block(cols=2, rows=2, layout="grid"):
|
||||
button at _fits_block align (0.5, 0.5):
|
||||
add phone.config.basedir + "airplane_icon.png"
|
||||
add phone.asset("airplane_icon.png")
|
||||
action If(
|
||||
phone.system.locked,
|
||||
NullAction(),
|
||||
@ -133,7 +135,7 @@ screen _phone_status_bar():
|
||||
)
|
||||
|
||||
button at _fits_block align (0.5, 0.5):
|
||||
add phone.config.basedir + "cellular_data_icon.png"
|
||||
add phone.asset("cellular_data_icon.png")
|
||||
action If(
|
||||
phone.system.locked,
|
||||
NullAction(),
|
||||
@ -142,11 +144,11 @@ screen _phone_status_bar():
|
||||
ToggleVariable("phone.system.cellular_data")
|
||||
)
|
||||
)
|
||||
selected_background Transform(phone.config.basedir + "circle.png", matrixcolor=TintMatrix("#35C759"), subpixel=True, fit="contain")
|
||||
selected_background Transform(phone.asset("circle.png"), matrixcolor=TintMatrix("#35C759"), subpixel=True, fit="contain")
|
||||
padding (90, 90)
|
||||
|
||||
button at _fits_block align (0.5, 0.5):
|
||||
add phone.config.basedir + "wifi_icon.png"
|
||||
add phone.asset("wifi_icon.png")
|
||||
action (
|
||||
If(
|
||||
phone.system.locked,
|
||||
@ -165,7 +167,7 @@ screen _phone_status_bar():
|
||||
)
|
||||
|
||||
button at _fits_block align (0.5, 0.5):
|
||||
add phone.config.basedir + "bluetooth_icon.png"
|
||||
add phone.asset("bluetooth_icon.png")
|
||||
action If(
|
||||
phone.system.locked,
|
||||
NullAction(),
|
||||
@ -179,21 +181,21 @@ screen _phone_status_bar():
|
||||
use _phone_control_center_block():
|
||||
button at _fits_block align (0.5, 0.5):
|
||||
if phone.system.rotation_locked:
|
||||
add phone.config.basedir + "rotation_locked_icon.png"
|
||||
add phone.asset("rotation_locked_icon.png")
|
||||
else:
|
||||
add phone.config.basedir + "rotation_unlocked_icon.png"
|
||||
add phone.asset("rotation_unlocked_icon.png")
|
||||
action ToggleVariable("phone.system.rotation_locked")
|
||||
|
||||
use _phone_control_center_block():
|
||||
button at _fits_block align (0.5, 0.5):
|
||||
add phone.config.basedir + "moon_icon.png"
|
||||
add phone.asset("moon_icon.png")
|
||||
action ToggleVariable("phone.system.dark_mode")
|
||||
|
||||
use _phone_control_center_block(cols=2):
|
||||
button at _yfits_block:
|
||||
style "empty" align (0.5, 0.5)
|
||||
hbox style "empty" yfill True:
|
||||
add phone.config.basedir + "screen_mirroring_icon.png" at _yfits(0.67) yalign 0.5
|
||||
add phone.asset("screen_mirroring_icon.png") at _yfits(0.67) yalign 0.5
|
||||
null width 10
|
||||
text _("Screen\nMirroring") size 14 yalign 0.5
|
||||
|
||||
@ -202,13 +204,13 @@ screen _phone_status_bar():
|
||||
hbox:
|
||||
use _phone_control_center_block():
|
||||
button at _fits_block align (0.5, 0.5):
|
||||
add phone.config.basedir + "flashlight_icon.png"
|
||||
add phone.asset("flashlight_icon.png")
|
||||
action ToggleVariable("phone.system.flashlight")
|
||||
padding (30, 30)
|
||||
|
||||
use _phone_control_center_block():
|
||||
button at _fits_block align (0.5, 0.5):
|
||||
add phone.config.basedir + "timer_icon.png"
|
||||
add phone.asset("timer_icon.png")
|
||||
action NullAction()
|
||||
padding (30, 30) hover_background None
|
||||
|
||||
@ -232,14 +234,14 @@ screen _phone_status_bar():
|
||||
|
||||
imagebutton:
|
||||
xysize (50, 50)
|
||||
selected_idle Transform(phone.config.basedir + "play_icon.png", fit="contain", subpixel=True, align=(0.5, 0.5))
|
||||
selected_hover Transform(phone.config.basedir + "play_icon.png", fit="contain", subpixel=True, align=(0.5, 0.5))
|
||||
selected_idle Transform(phone.asset("play_icon.png"), fit="contain", subpixel=True, align=(0.5, 0.5))
|
||||
selected_hover Transform(phone.asset("play_icon.png"), fit="contain", subpixel=True, align=(0.5, 0.5))
|
||||
|
||||
if renpy.music.get_playing("phone_music") is None:
|
||||
idle Transform(phone.config.basedir + "play_icon.png", fit="contain", subpixel=True, align=(0.5, 0.5))
|
||||
idle Transform(phone.asset("play_icon.png"), fit="contain", subpixel=True, align=(0.5, 0.5))
|
||||
action (NullAction(), SelectedIf(False))
|
||||
else:
|
||||
idle Transform(phone.config.basedir + "pause_icon.png", fit="contain", subpixel=True, align=(0.5, 0.5))
|
||||
idle Transform(phone.asset("pause_icon.png"), fit="contain", subpixel=True, align=(0.5, 0.5))
|
||||
action PauseAudio("phone_music", "toggle")
|
||||
|
||||
button style "empty" yalign 0.5:
|
||||
@ -252,7 +254,7 @@ screen _phone_status_bar():
|
||||
hbox:
|
||||
use _phone_control_center_block(rows=2):
|
||||
vbar value FieldValue(phone.system, "brightness", 1.0 - phone.config.lowest_brightness, offset=phone.config.lowest_brightness)
|
||||
add phone.config.basedir + "sun_icon.png":
|
||||
add phone.asset("sun_icon.png"):
|
||||
at transform:
|
||||
subpixel True xysize (0.5, 0.5) fit "contain"
|
||||
xalign 0.5 yalign 0.75
|
||||
@ -264,11 +266,11 @@ screen _phone_status_bar():
|
||||
add DynamicDisplayable(
|
||||
lambda st, at: (
|
||||
(
|
||||
phone.config.basedir + "volume_icon_0.png"
|
||||
phone.asset("volume_icon_0.png")
|
||||
if get_mixer("phone") == 0.0
|
||||
else phone.config.basedir + "volume_icon_1.png"
|
||||
else phone.asset("volume_icon_1.png")
|
||||
if get_mixer("phone") < 0.5
|
||||
else phone.config.basedir + "volume_icon_2.png"
|
||||
else phone.asset("volume_icon_2.png")
|
||||
),
|
||||
0.1
|
||||
)
|
||||
@ -281,20 +283,20 @@ screen _phone_status_bar():
|
||||
hbox:
|
||||
use _phone_control_center_block():
|
||||
button at _fits_block align (0.5, 0.5):
|
||||
add phone.config.basedir + "calculator_icon.png"
|
||||
add phone.asset("calculator_icon.png")
|
||||
action NullAction()
|
||||
padding (30, 30) hover_background None
|
||||
|
||||
use _phone_control_center_block():
|
||||
button at _fits_block align (0.5, 0.5):
|
||||
add phone.config.basedir + "camera_icon.png"
|
||||
add phone.asset("camera_icon.png")
|
||||
action NullAction()
|
||||
padding (30, 30) hover_background None
|
||||
|
||||
screen _phone_control_center_block(cols=1, rows=1, layout="empty"):
|
||||
frame at Flatten:
|
||||
# https://github.com/renpy/renpy/issues/4666 >=
|
||||
if renpy.version_tuple[:2] > ((7, 6) if renpy.compat.PY2 else (8, 1)):
|
||||
frame at (CurriedRoundedCorners(radius=gui.phone_control_center_block_rounded_corners_radius), Flatten):
|
||||
# https://github.com/renpy/renpy/issues/4666
|
||||
if is_renpy_version_or_above(7, 6, 1):
|
||||
xysize (
|
||||
absolute((gui.phone_control_center_block_size * cols) + (gui.phone_control_center_spacing * (cols - 1))),
|
||||
absolute((gui.phone_control_center_block_size * rows) + (gui.phone_control_center_spacing * (rows - 1)))
|
||||
@ -342,7 +344,7 @@ style _phone_status_bar_text is empty:
|
||||
color "#fff" outlines [ ]
|
||||
size 12 line_spacing 0
|
||||
yalign 0.5
|
||||
font phone.config.basedir + "Aller_Rg.ttf"
|
||||
font phone.asset("Aller_Rg.ttf")
|
||||
|
||||
transform _fits_block(factor=gui.phone_control_center_block_scaling_factor):
|
||||
_fits(absolute(gui.phone_control_center_block_size * factor))
|
||||
@ -366,7 +368,7 @@ style _phone_control_center_hbox is empty:
|
||||
style _phone_control_center_vbox is empty:
|
||||
spacing gui.phone_control_center_spacing
|
||||
|
||||
image _phone_control_center_bar = RoundedFrame("#fafafa", radius=gui.phone_control_center_block_rounded_corners_radius, outline_color="#f7f7f7d8", outline_width=1)
|
||||
image _phone_control_center_bar = "#fafafa"
|
||||
|
||||
style _phone_control_center_bar is empty:
|
||||
left_bar "_phone_control_center_bar"
|
||||
@ -378,13 +380,13 @@ style _phone_control_center_vbar is empty:
|
||||
style _phone_control_center_button is empty:
|
||||
padding (70, 70)
|
||||
background None
|
||||
hover_background Transform(phone.config.basedir + "circle.png", matrixcolor=TintMatrix("#5a5a5a"), subpixel=True, fit="contain")
|
||||
selected_background Transform(phone.config.basedir + "circle.png", matrixcolor=TintMatrix("#007BFA"), subpixel=True, fit="contain")
|
||||
insensitive_background Transform(phone.config.basedir + "circle.png", matrixcolor=TintMatrix("#b1b1b1"), subpixel=True, fit="contain")
|
||||
hover_background Transform(phone.asset("circle.png"), matrixcolor=TintMatrix("#5a5a5a"), subpixel=True, fit="contain")
|
||||
selected_background Transform(phone.asset("circle.png"), matrixcolor=TintMatrix("#007BFA"), subpixel=True, fit="contain")
|
||||
insensitive_background Transform(phone.asset("circle.png"), matrixcolor=TintMatrix("#b1b1b1"), subpixel=True, fit="contain")
|
||||
|
||||
style _phone_control_center_block_frame is empty:
|
||||
modal True
|
||||
background RoundedFrame("#000000d0", radius=gui.phone_control_center_block_rounded_corners_radius, outline_color="#00000093", outline_width=1)
|
||||
background "#000000d0"
|
||||
|
||||
style _phone_control_center_block_base_box is empty:
|
||||
spacing int(gui.phone_control_center_spacing + (gui.phone_control_center_block_size * (1.0 - gui.phone_control_center_block_scaling_factor) * 0.5))
|
||||
|
@ -2,6 +2,7 @@ init -999:
|
||||
define config.gl2 = True
|
||||
define config.early_start_store = False
|
||||
|
||||
# Some of these definitions are overwrote in 01definitions.rpy
|
||||
init -200:
|
||||
define gui.phone_margin = (15, 81, 15, 94)
|
||||
define gui.phone_zoom = 0.8
|
||||
@ -30,6 +31,22 @@ init -200:
|
||||
python early:
|
||||
import collections, pygame_sdl2 as pygame
|
||||
|
||||
@renpy.pure
|
||||
def is_renpy_version_or_above(major, minor, patch):
|
||||
"""
|
||||
Checks if the current version of renpy is at least `(major, minor, patch)`.
|
||||
If renpy is on a py3 / r8 version, `(major + 1, minor - 5, patch)` is checked.
|
||||
|
||||
I.e., if the game runs on renpy 8 and that this function is called to check for `7.5.0`, `8.0.0` (the py3 / r8 equivalent of `7.5.0`) is checked for.
|
||||
"""
|
||||
current_version = renpy.version_tuple[:3]
|
||||
|
||||
if not renpy.compat.PY2:
|
||||
major += 1
|
||||
minor -= 5
|
||||
|
||||
return current_version >= (major, minor, patch)
|
||||
|
||||
def hyperlink_functions_style(name):
|
||||
"""
|
||||
Hyperlink functions but the style `name` is used.
|
||||
@ -40,7 +57,7 @@ python early:
|
||||
style_object = getattr(style, name)
|
||||
return (lambda target: style_object,) + style.default.hyperlink_functions[1:]
|
||||
|
||||
if renpy.version_tuple[:2] >= ((7, 6) if renpy.compat.PY2 else (8, 1)):
|
||||
if is_renpy_version_or_above(7, 6, 0):
|
||||
def get_mixer(mixer):
|
||||
return preferences.get_mixer(mixer)
|
||||
else:
|
||||
@ -65,67 +82,72 @@ python early:
|
||||
b = a * col[2] / 255.0
|
||||
return (r, g, b, a)
|
||||
|
||||
# RoundedFrame by pseurae
|
||||
# https://gist.github.com/Pseurae/661e6084f756fc917b2889a386b16664
|
||||
# modified by yours truly (i don't know shit about OpenGL)
|
||||
class RoundedFrame(renpy.display.image.Frame):
|
||||
def __init__(self, image, *args, **kwargs):
|
||||
radius = kwargs.pop("radius", 0.0)
|
||||
outline_width = kwargs.pop("outline_width", 0.0)
|
||||
outline_color = kwargs.pop("outline_color", "#fff")
|
||||
_rounded_corners_relative = {
|
||||
None: 0.0,
|
||||
"min": 1.0,
|
||||
"max": 2.0,
|
||||
"width": 3.0,
|
||||
"height": 4.0,
|
||||
}
|
||||
|
||||
super(RoundedFrame, self).__init__(image, *args, **kwargs)
|
||||
|
||||
if not isinstance(radius, tuple): radius = (radius,) * 4
|
||||
self.radius = radius
|
||||
def RoundedCorners(child, radius, relative=None, outline_width=0.0, outline_color="#fff", **kwargs):
|
||||
if not isinstance(radius, tuple): radius = (radius,) * 4
|
||||
relative = _rounded_corners_relative[relative]
|
||||
outline_color = normalize_color(Color(outline_color))
|
||||
return Transform(child, mesh=True, shader="shader.rounded_corners", u_radius=radius, u_relative=relative, u_outline_color=outline_color, u_outline_width=outline_width, **kwargs)
|
||||
|
||||
self.outline_width = outline_width
|
||||
self.outline_color = normalize_color(Color(outline_color))
|
||||
|
||||
def render(self, w, h, st, at):
|
||||
rv = super(RoundedFrame, self).render(w, h, st, at)
|
||||
|
||||
if self.radius:
|
||||
rv.mesh = True
|
||||
rv.add_property("gl_pixel_perfect", True)
|
||||
rv.add_property("gl_mipmap", False)
|
||||
rv.add_property("texture_scaling", "nearest")
|
||||
rv.add_shader("shader.rounded_corners")
|
||||
rv.add_uniform("u_radius", self.radius)
|
||||
rv.add_uniform("u_outline_width", self.outline_width)
|
||||
rv.add_uniform("u_outline_color", self.outline_color)
|
||||
|
||||
return rv
|
||||
CurriedRoundedCorners = renpy.curry(RoundedCorners)
|
||||
|
||||
renpy.register_shader("shader.rounded_corners", variables="""
|
||||
uniform vec4 u_radius;
|
||||
uniform float u_outline_width;
|
||||
uniform vec4 u_outline_color;
|
||||
uniform float u_relative;
|
||||
uniform sampler2D tex0;
|
||||
attribute vec2 a_tex_coord;
|
||||
varying vec2 v_tex_coord;
|
||||
uniform vec2 res0;
|
||||
uniform vec2 u_model_size;
|
||||
""", vertex_200="""
|
||||
v_tex_coord = a_tex_coord;
|
||||
""", fragment_functions="""
|
||||
// https://www.iquilezles.org/www/articles/distfunctions/distfunctions2d.htm
|
||||
float rounded_rectangle(in vec2 p, in vec2 b, in vec4 r) {
|
||||
r.xy = (p.x > 0.0) ? r.xy : r.zw;
|
||||
r.x = (p.y > 0.0) ? r.x : r.y;
|
||||
vec2 q = abs(p) - b + r.x;
|
||||
return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r.x;
|
||||
float rounded_rectangle(vec2 p, vec2 b, float r) {
|
||||
return length(max(abs(p) - b + r, 0.0)) - r;
|
||||
}
|
||||
|
||||
float get_radius(vec2 uv_minus_center, vec4 radius) {
|
||||
vec2 xy = (uv_minus_center.x > 0.0) ? radius.xy : radius.zw;
|
||||
float r = (uv_minus_center.y > 0.0) ? xy.x : xy.y;
|
||||
return r;
|
||||
}
|
||||
""", fragment_200="""
|
||||
vec2 center = u_model_size.xy / 2.0;
|
||||
vec2 uv = (v_tex_coord.xy * u_model_size.xy);
|
||||
|
||||
vec2 uv_minus_center = uv - center;
|
||||
float radius = get_radius(uv_minus_center, u_radius);
|
||||
|
||||
vec4 color = texture2D(tex0, v_tex_coord);
|
||||
|
||||
if (u_relative != 0.0) {
|
||||
float side_size;
|
||||
if (u_relative == 1.0) {
|
||||
side_size = u_model_size.x;
|
||||
} else if (u_relative == 2.0) {
|
||||
side_size = u_model_size.y;
|
||||
} else if (u_relative == 3.0) {
|
||||
side_size = min(u_model_size.x, u_model_size.y);
|
||||
} else {
|
||||
side_size = max(u_model_size.x, u_model_size.y);
|
||||
}
|
||||
|
||||
radius *= side_size;
|
||||
}
|
||||
|
||||
if (u_outline_width > 0.0) {
|
||||
vec2 center_outline = center - u_outline_width;
|
||||
|
||||
float crop1 = rounded_rectangle(uv - center, center, vec4(u_radius));
|
||||
float crop2 = rounded_rectangle(uv - center, center_outline, vec4(u_radius - u_outline_width));
|
||||
float crop1 = rounded_rectangle(uv - center, center, radius);
|
||||
float crop2 = rounded_rectangle(uv - center, center_outline, radius - u_outline_width);
|
||||
|
||||
float coeff1 = smoothstep(1.0, -1.0, crop1);
|
||||
float coeff2 = smoothstep(1.0, -1.0, crop2);
|
||||
@ -135,11 +157,12 @@ python early:
|
||||
gl_FragColor = mix(vec4(0.0), mix(color, u_outline_color, outline_coeff), coeff1);
|
||||
}
|
||||
else {
|
||||
float crop = rounded_rectangle(uv - center, center, vec4(u_radius));
|
||||
gl_FragColor = mix(vec4(0.0), color, smoothstep(1.0, 0.0, crop));
|
||||
float crop = rounded_rectangle(uv_minus_center, center, radius);
|
||||
gl_FragColor = mix(color, vec4(0.0), smoothstep(0.0, 1.0, crop));
|
||||
}
|
||||
""")
|
||||
|
||||
|
||||
# taken from
|
||||
# https://github.com/WretchedTeam/WintermuteV3/blob/main/game/mod_code/backend/displayables.rpy
|
||||
class ShaderDisplayable(renpy.Displayable):
|
||||
|
@ -50,5 +50,5 @@ define discord.start_label = "storyline"
|
||||
# These variables control the print functions across this script. They work if True, they're ignored if False.
|
||||
# Prints are shown inside game's console (if turned on in the Ren'Py Launcher) and in the game's log.txt file.
|
||||
define discord.log_important = True # Shows whether the Presence was initialized and closed correctly.
|
||||
define discord.log_properties = True # Records properties whenever they change with set or update methods.
|
||||
define discord.log_properties = False # Records properties whenever they change with set or update methods.
|
||||
define discord.log_restore = True # Notes whenever the properties get rolled back or loaded from a save file, and what they were restored into.
|
@ -9,13 +9,27 @@ default ben_story = None
|
||||
|
||||
label after_load:
|
||||
if not renpy.android:
|
||||
|
||||
# renpy.get_return_stack()[1] will basically return what chapter the user is currently in the save, we call index 1 since index 0 will always be the label storyline from storyline.rpy. Keep in mind the name used will be what the 'from clause' adds in the call
|
||||
|
||||
# If the player went past chapter 2 without seeing the caligraphy CG then they are on a save from the first version of the game
|
||||
if not persistent.seen_notice and not renpy.seen_image("cg_calligraphy") and (renpy.get_return_stack()[1][0] == '_call_chapter_3' or renpy.get_return_stack()[1][0] == '_call_chapter_4'):
|
||||
if not persistent.seen_notice and not renpy.seen_image("cg_calligraphy") and (renpy.get_return_stack()[1] == '_call_chapter_3' or renpy.get_return_stack()[1] == '_call_chapter_4'):
|
||||
call old_save_notice from _call_old_save_notice
|
||||
call ask_drawing from _call_ask_drawing
|
||||
$ renpy.block_rollback()
|
||||
|
||||
if ben_story == None and isinstance(renpy.get_return_stack()[1][0], str) and renpy.get_return_stack()[1][0].startswith("chapter_"):
|
||||
# However this is not always reliable, sometimes it will fail, this is why it's in a try block and why we check that
|
||||
# 1. We are checking a story script ("_call_chapter_"), since all of this won't work in mods and such
|
||||
# 2. Check we are actually checking a string, since sometimes index 1 will be a tuple that points to a specific line instead (I don't know why this happens)
|
||||
|
||||
python:
|
||||
try:
|
||||
needs_compat = isinstance(renpy.get_return_stack()[1], str) and renpy.get_return_stack()[1].startswith("_call_chapter_")
|
||||
except:
|
||||
needs_compat = False
|
||||
|
||||
if ben_story == None and needs_compat:
|
||||
# This ensures that mods won't trigger the save compatibility
|
||||
if hasattr(store, 'score_olivia'):
|
||||
call initstats(score_olivia,score_inco) from _call_initstats_4
|
||||
call ask_drawing from _call_ask_drawing_1
|
||||
@ -123,6 +137,8 @@ label AskChoices:
|
||||
|
||||
jump newContent
|
||||
|
||||
|
||||
# Adds a custom error handler for the error of 'Couldn't find a place to stop rolling back' (Which usually happens when the save is incompatible). This error handler sends the user to a screen informing them of this and then to the menu instead of showing the gray exception screen.
|
||||
init python:
|
||||
def handle_bad_save(shortException,longException,tracebackFile):
|
||||
if "Exception: Couldn't find a place to stop rolling back. Perhaps the script changed in an incompatible way?" in shortException and not config.developer:
|
||||
@ -155,13 +171,16 @@ screen badSave():
|
||||
xalign 0.5
|
||||
spacing 100
|
||||
|
||||
# I originally wanted to send you to the main menu but that really really breaks for some reason
|
||||
textbutton _("OK") activate_sound "audio/ui/snd_ui_click.wav" action Jump("kill_playthrough")
|
||||
|
||||
# For some reason, sending to the main menu won't work and instead it'll start a new (broken) game. SO instead, we clear the return stack and then return. Since it's cleared Renpy thinks "The game's over, send them back to the menu" and this for some reason jest werks.
|
||||
label kill_playthrough:
|
||||
# Stupid way to return to the main menu, the traditional ways don't work or outright crash the game
|
||||
$ renpy.set_return_stack([])
|
||||
return
|
||||
|
||||
|
||||
# If there's no drawing saved we ask the player to either draw a new one or to import it
|
||||
label ask_drawing:
|
||||
if type(waniDemoCarryover.Chapter3Drawing) == NoneType:
|
||||
|
||||
@ -195,6 +214,7 @@ label ask_drawing:
|
||||
with open(filename, mode="rb") as filecontents:
|
||||
waniDemoCarryover.Chapter3Drawing = filecontents.read()
|
||||
|
||||
# We close the file just in case and then we replace with None otherwise renpy tries to pickle the variable for saving and fails.
|
||||
filecontents.close()
|
||||
filecontents = None
|
||||
|
||||
@ -211,7 +231,7 @@ label ask_drawing:
|
||||
shutil.copyfile(filename, new_folder)
|
||||
except:
|
||||
pass
|
||||
# Needed unless renpy throws a fit when saving
|
||||
# Same as with filecontents. Needed unless renpy throws a fit when saving.
|
||||
renpy.store.shutil = None
|
||||
|
||||
if filename == None or not filename.endswith(".png"):
|
||||
|
@ -1,16 +1,9 @@
|
||||
|
||||
label splashscreen:
|
||||
$ persistent.splashtype = random.randint(0,2000 - 1)
|
||||
|
||||
show anim_caveintro
|
||||
play sound mus_startup
|
||||
pause 11.2
|
||||
stop sound
|
||||
|
||||
if (persistent.languaged_up is None):
|
||||
$ persistent.languaged_up = True
|
||||
$ preferences.set_volume('ui', config.default_sfx_volume) # hack
|
||||
call screen lang_sel
|
||||
|
||||
if not renpy.get_autoreload():
|
||||
show anim_caveintro
|
||||
play sound mus_startup
|
||||
pause 11.2
|
||||
stop sound
|
||||
|
||||
return
|
@ -25,7 +25,7 @@ screen OkPrompt(message, go_menu):
|
||||
xalign 0.5
|
||||
spacing 100
|
||||
|
||||
textbutton _("OK") activate_sound "audio/ui/snd_ui_click.wav" action If(go_menu, true=MainMenu(False,False), false=Return())
|
||||
textbutton _("OK") activate_sound "audio/ui/snd_ui_click.wav" action If(go_menu, true=MainMenu(False,False), false=[Hide(),Return()])
|
||||
|
||||
screen hiddenOkPrompt(message, go_menu):
|
||||
|
||||
@ -133,9 +133,9 @@ screen lang_sel():
|
||||
idle darkie(languages[i]["image"])
|
||||
hover glowie(languages[i]["image"])
|
||||
action If(languages[i]["value"] in persistent.seenWarning or languages[i]["value"] == None,
|
||||
true = [Language(languages[i]["value"]), MainMenu(False,False)],
|
||||
true = [Language(languages[i]["value"]), Return()],
|
||||
# Important to change the language before calling notice. Otherwise it will be in english.
|
||||
false = [Language(languages[i]["value"]), AddToSet(set=persistent.seenWarning, value=languages[i]["value"]), Show(screen="OkPrompt", message=notice, go_menu=True)]
|
||||
false = [Language(languages[i]["value"]), AddToSet(set=persistent.seenWarning, value=languages[i]["value"]), Show(screen="OkPrompt", message=notice, go_menu=False)]
|
||||
)
|
||||
at renpysdumb # Scales the imagebutton down. No, you can't just specify the zoom here. It has to be a defined transform.
|
||||
else:
|
||||
|
@ -194,7 +194,13 @@ init python:
|
||||
damp = 1
|
||||
if self.damped and self.end is not None:
|
||||
damp = renpy.atl.warpers[self.damped_warper]((self.end - st / self.fast_forward) / self.end)
|
||||
offset = damp * renpy.atl.interpolate_spline(g, self.random_knot)
|
||||
|
||||
if renpy.version_tuple[3] >= 24011600:
|
||||
interpolate_spline = renpy.atl.interpolate_spline(g, self.random_knot, renpy.atl.PROPERTIES[self.property])
|
||||
else:
|
||||
interpolate_spline = renpy.atl.interpolate_spline(g, self.random_knot)
|
||||
|
||||
offset = damp * interpolate_spline
|
||||
setattr(tran, self.property, offset)
|
||||
return 0
|
||||
|
||||
|
@ -64,6 +64,8 @@ init -1600 python in _viewers:
|
||||
default_channel_list = ["sound"]
|
||||
#default side view.
|
||||
default_sideview = True
|
||||
#Not included layers
|
||||
not_included_layer = ("transient", "screens", "overlay")
|
||||
|
||||
default_graphic_editor_narrow_range = 2.
|
||||
default_graphic_editor_wide_range = 2000
|
||||
|
@ -2,8 +2,8 @@
|
||||
日本語マニュアルはドキュメント後半にあります。
|
||||
|
||||
This script adds Ren'py the ability to adjust and view transform properties of images
|
||||
and camera by in-game Action Editor and Image Viewer and Sound Viewer.
|
||||
Many warpers and usefull functions intended to be used in function statement in ATL are
|
||||
and camera by in-game Action Editor, Image Viewer and Sound Viewer.
|
||||
Many warpers and useful functions intended to be used in function statements in ATL are
|
||||
also added.
|
||||
|
||||
Ren'Py <http://www.renpy.org/>
|
||||
@ -26,32 +26,32 @@ lemma forum
|
||||
================
|
||||
|
||||
This script adds Ren'py the ability to adjust and view transform properties of images
|
||||
and camera by in-game Action Editor and Image Viewer and Sound Viewer.
|
||||
Many warpers and usefull functions intended to be used in function statement in ATL are
|
||||
and camera by in-game Action Editor, Image Viewer and Sound Viewer.
|
||||
Many warpers and useful functions intended to be used in function statements in ATL are
|
||||
also added.
|
||||
|
||||
About old version
|
||||
================
|
||||
This is available in v7.4.5 later.
|
||||
To use in older version, use old version ActionEditor.
|
||||
To use an older version, use the old version of ActionEditor.
|
||||
<https://github.com/kyouryuukunn/renpy-ActionEditor>
|
||||
|
||||
In current version ActionEditor, below functions are removed.
|
||||
|
||||
In the current version of ActionEditor, the below functions are removed.
|
||||
* expression
|
||||
* loading last action
|
||||
|
||||
To instal
|
||||
To install
|
||||
================
|
||||
To install, copy all files in the camera directory into your game directory.
|
||||
ActionEditor.rpy is required for release version if you use camera blur or warper_generator.
|
||||
00warper.rpy is also required if you use added warpers.
|
||||
ATL_funcctions.rpy is also required if you use added functions for ATL statement.
|
||||
Ohter files arenot required.
|
||||
Other files are not required.
|
||||
|
||||
Action Editor
|
||||
================
|
||||
|
||||
This allows you to adjusts transform properties of camera and images in
|
||||
This allows you to adjust transform properties of camera and images in
|
||||
real-time with a GUI. It can then generate a script based on these changes and
|
||||
place it on the clipboard for later pasting into Ren'Py scripts.
|
||||
|
||||
@ -60,32 +60,32 @@ lemma forum
|
||||
|
||||
The Action Editor has the following features:
|
||||
|
||||
* View and adjust the transform properties of images and camera with adjusting a bar or typing value.
|
||||
* View and adjust the transform properties of images and camera by adjusting a bar or typing a value.
|
||||
* View and adjust the x and y coordinates of the camera with a draggable camera icon.
|
||||
* Adjust the z coordinate of the camera with the mouse wheel.
|
||||
* Adjust the x,y coordinate of the camera with the keyboard(hjkl, HJKL, wasd, WASD).
|
||||
* Reset the value with right-click on the value button.
|
||||
* Reset the value by right-clicking on the value button.
|
||||
* Add, delete, and edit keyframes on a timeline like video editing software.
|
||||
* the spline motion and loop is availabe
|
||||
* The spline motion and loop is available
|
||||
* After setting up a scene with the desired look and animations, the Action
|
||||
Editor will generate a script and place it on your clipboard for pasting
|
||||
into your Ren'Py scripts. (v6.99 and later only)
|
||||
* Introducing the concept of depth of field and allow to adjust focus position and dof.
|
||||
Blur each image according to dof, focus postion and the distance between the camera and the image.
|
||||
Blur each image according to dof, focus position and the distance between the camera and the image.
|
||||
* Show, replace and hide a image with transition(use None for a image name to hide image)
|
||||
* Change a scene with scene statement.
|
||||
* There is the option for hiding window during the ATL animation in clipboard data.
|
||||
* There is the option for allowing to skip ATL animation in clipboard data.
|
||||
|
||||
Note
|
||||
* blur transform property of each images are used for simulating camera blur in function transform prperty,
|
||||
so blur transform properties of each images aren't availabe when focusing is enabled.
|
||||
Set function property to None when you want to disable camera blur for already shownd images.
|
||||
* Unfortunately, The behavior of functions for function property isn't same as ATL.
|
||||
* blur transform property of each images are used for simulating camera blur in function transform property,
|
||||
so blur transform properties of each images aren't available when focusing is enabled.
|
||||
Set function property to None when you want to disable camera blur for already shown images.
|
||||
* Unfortunately, The behavior of functions for function property isn't the same as ATL.
|
||||
There are some different points.
|
||||
1. inherited_<property> have no value.
|
||||
2. Setting properties have no affect when it is called next time.
|
||||
3. The return value from it have no affect.
|
||||
2. Setting properties have no effect when it is called next time.
|
||||
3. The return value from it has no effect.
|
||||
4. It isn't always called in time.
|
||||
ActionEditor can't get current function when opened.
|
||||
|
||||
@ -102,8 +102,8 @@ lemma forum
|
||||
|
||||
Commonly, add the following variables the property name you want to add to be added.:
|
||||
|
||||
* `props_set`: control where that is shwon in ActionEditor.
|
||||
* `sort_order_list`: control where that is shwon in clipboard.
|
||||
* `props_set`: control where that is shown in ActionEditor.
|
||||
* `sort_order_list`: control where that is shown in the clipboard.
|
||||
* `transform_props` or `camera_props`: Add the the property name.
|
||||
Adding `transform_props` shows it in each images and Adding `camera_props` shows it in camera.
|
||||
* `property_default_value`: Add the default value of the property.
|
||||
@ -137,7 +137,7 @@ lemma forum
|
||||
any_props = {"blend"}
|
||||
menu_props = {"blend":[None] + [key for key in config.gl_blend_func]}
|
||||
|
||||
Exclusive proparties like tile and pan should be set in `exclusive`. example:
|
||||
Exclusive properties like tile and pan should be set in `exclusive`. example:
|
||||
|
||||
exclusive = (
|
||||
({"xpos", "ypos"}, {"xalignaround", "yalignaround", "radius", "angle"}),
|
||||
@ -148,7 +148,7 @@ lemma forum
|
||||
Property Group
|
||||
================
|
||||
|
||||
For tuple, You can use `props_groups` where that key is the property name and that value
|
||||
For tuples, you can use `props_groups` where that key is the property name and that value
|
||||
is the tuple of each element name, so that they can be edited individually. example:
|
||||
|
||||
props_groups = {
|
||||
@ -164,18 +164,18 @@ lemma forum
|
||||
If `config.developer` is True, pressing Shift+U or +(add image) textbutton on ActionEditor
|
||||
to open Image Viewer.
|
||||
|
||||
Defined image tag and attribute textbuttons are shown in this viewer.
|
||||
Defined image tags and attribute textbuttons are shown in this viewer.
|
||||
You can filter them by the text entered in the top-most text entry field.
|
||||
The completion feature is also availabe by tab.
|
||||
The completion feature is also available by tab.
|
||||
|
||||
When these textbuttons get focus and the same image name exist as these text, the image is
|
||||
When these textbuttons get focus and the same image name exists as these text, the image is
|
||||
shown.
|
||||
Pressing the textbutton add that text to the filter if the same image name doesn't exist
|
||||
as that text. the image is added to ActionEditor if that exist and viewer is opened by
|
||||
ActionEditor. the image name is outputted to the clipboard if that exist and viewer isn't
|
||||
opened by ActionEditor.
|
||||
|
||||
Pressing clipboard buton at the bottom also outputs the filter string to clipboard
|
||||
Pressing clipboard button at the bottom also outputs the filter string to clipboard
|
||||
|
||||
|
||||
Sound Viewer
|
||||
@ -186,17 +186,17 @@ lemma forum
|
||||
Variable names in audio store are shown in this viewer.
|
||||
The music files should be automatically defined as these name.
|
||||
You can filter them by the text entered in the top-most text entry field.
|
||||
The completion feature is also availabe by tab.
|
||||
The completion feature is also available by tab.
|
||||
|
||||
When these textbuttons get focus and the music file is played.
|
||||
Pressing the textbutton add that to ActionEditor if the viewer is opened by ActionEditor.
|
||||
Pressing the textbutton adds that to ActionEditor if the viewer is opened by ActionEditor.
|
||||
Otherwise, that name is outputted to the clipboard.
|
||||
|
||||
Pressing clipboard buton at the bottom also outputs the filter string to clipboard
|
||||
Pressing clipboard button at the bottom also outputs the filter string to clipboard
|
||||
|
||||
ATL functions
|
||||
================
|
||||
ATL_funcctions.rpy adds usefull functions which are intended to be used for
|
||||
ATL_funcctions.rpy adds useful functions which are intended to be used for
|
||||
function statement in ATL block. For more information, see that file.
|
||||
|
||||
|
||||
@ -235,23 +235,28 @@ lemma forum
|
||||
style new_action_editor_text:
|
||||
size 10
|
||||
|
||||
Trouble shooting
|
||||
Troubleshooting
|
||||
================
|
||||
|
||||
Layout is corrupted
|
||||
|
||||
Too long tag names and big size of fonts corrupt the layout of ActionEditor.
|
||||
Too long tag names and big font sizes corrupt the layout of ActionEditor.
|
||||
In that case, try to adjust the size of font by the above manner.
|
||||
|
||||
|
||||
Known issue
|
||||
================
|
||||
|
||||
ActionEditor can't show camera and displayable with "at clause" includeing animation correctly.
|
||||
ActionEditor can't show camera and displayable with "at clause" including animation correctly.
|
||||
|
||||
ActionEditor can't show movie and animation displayable correctly.
|
||||
|
||||
|
||||
Note
|
||||
================
|
||||
|
||||
The clipboard from ActionEditor includes the difference from the state when ActionEditor is opened on. Therefore that is intended to be pasted on next that line. Images aren't shown correctly if the existing lines are overwritten.
|
||||
|
||||
|
||||
日本語ドキュメント
|
||||
================
|
||||
@ -497,3 +502,8 @@ lemma forum
|
||||
アニメーションするat 節を使用したcamera, displayableは正常に表示できない
|
||||
|
||||
Movie Displayable, アニメーションするDisplayableは正常に表示できない
|
||||
|
||||
注意
|
||||
================
|
||||
|
||||
ActionEditorから出力されるクリップボードデータはActionEditorが開かれた状態からの差分として出力され、その次の行への貼り付けを意図しています。このため既存のshowステートメントを上書きするように貼り付けると正常に表示されない場合があります。
|
||||
|
@ -11,6 +11,7 @@ screen _image_selecter(default=""):
|
||||
style_group "image_selecter"
|
||||
vbox:
|
||||
label _("Type a image name") style "image_selecter_input"
|
||||
label _("Tab: completion") style "image_selecter_input"
|
||||
input value ScreenVariableInputValue("filter_string", default=True, returnable=True) copypaste True style "image_selecter_input" id "input_filter_strings"
|
||||
$filtered_list = _viewers.filter_image_name(filter_string)
|
||||
viewport:
|
||||
@ -101,10 +102,22 @@ init -2000 python in _viewers:
|
||||
for e in es.split()[1:]:
|
||||
if e.startswith(completed_string):
|
||||
candidate.append(e)
|
||||
cs = renpy.current_screen()
|
||||
cs.scope["filter_string"] += candidate[0][len(completed_string):] + " "
|
||||
input = renpy.get_displayable("_image_selecter", "input_filter_strings")
|
||||
input.caret_pos = len(cs.scope["filter_string"])
|
||||
|
||||
if candidate:
|
||||
cs = renpy.current_screen()
|
||||
if len(candidate) > 1:
|
||||
completed_candidate = candidate[0]
|
||||
for c in candidate[1:]:
|
||||
for i in range(len(completed_candidate)):
|
||||
if i < len(c) and completed_candidate[i] != c[i]:
|
||||
completed_candidate = completed_candidate[0:i]
|
||||
break
|
||||
cs.scope["filter_string"] += completed_candidate[len(completed_string):]
|
||||
else:
|
||||
completed_candidate = candidate[0]
|
||||
cs.scope["filter_string"] += completed_candidate[len(completed_string):] + " "
|
||||
input = renpy.get_displayable("_image_selecter", "input_filter_strings")
|
||||
input.caret_pos = len(cs.scope["filter_string"])
|
||||
|
||||
def _image_viewer_hide():
|
||||
renpy.hide("preview", layer="screens")
|
||||
|
@ -11,6 +11,7 @@ screen _sound_selector(default=""):
|
||||
style_group "sound_selecter"
|
||||
vbox:
|
||||
label _("type filenames(ex: variable, '<silence 2.>' or [[variable, variable])") style "sound_selecter_input"
|
||||
label _("Tab: completion") style "sound_selecter_input"
|
||||
input value ScreenVariableInputValue("filter_string", default=True, returnable=True) copypaste True style "sound_selecter_input" id "input_filter_strings"
|
||||
$filtered_list = _viewers.filter_sound_name(filter_string)
|
||||
viewport:
|
||||
@ -95,8 +96,17 @@ init -2000 python in _viewers:
|
||||
if isinstance(file, str) and renpy.loadable(file):
|
||||
candidate.append(name)
|
||||
if candidate:
|
||||
if len(candidate) > 1:
|
||||
completed_candidate = candidate[0]
|
||||
for c in candidate[1:]:
|
||||
for i in range(len(completed_candidate)):
|
||||
if i < len(c) and completed_candidate[i] != c[i]:
|
||||
completed_candidate = completed_candidate[0:i]
|
||||
break
|
||||
else:
|
||||
completed_candidate = candidate[0]
|
||||
cs = renpy.current_screen()
|
||||
cs.scope["filter_string"] += candidate[0][len(last_element):]
|
||||
cs.scope["filter_string"] += completed_candidate[len(last_element):]
|
||||
input = renpy.get_displayable("_sound_selector", "input_filter_strings")
|
||||
input.caret_pos = len(cs.scope["filter_string"])
|
||||
|
||||
|
BIN
game/dev/metro/bg_metro empty.png
Normal file
After Width: | Height: | Size: 2.2 MiB |
BIN
game/dev/metro/bg_metro olivia.png
Normal file
After Width: | Height: | Size: 2.2 MiB |
BIN
game/dev/metro/bg_metro passengers.png
Normal file
After Width: | Height: | Size: 2.1 MiB |
BIN
game/dev/old/ben/ben angry.png
Normal file
After Width: | Height: | Size: 353 KiB |
BIN
game/dev/old/ben/ben considering.png
Normal file
After Width: | Height: | Size: 322 KiB |
BIN
game/dev/old/ben/ben explanatory.png
Normal file
After Width: | Height: | Size: 295 KiB |
BIN
game/dev/old/ben/ben happy.png
Normal file
After Width: | Height: | Size: 298 KiB |
BIN
game/dev/old/ben/ben neutral.png
Normal file
After Width: | Height: | Size: 289 KiB |
BIN
game/dev/old/ben/ben sad.png
Normal file
After Width: | Height: | Size: 301 KiB |
BIN
game/dev/old/ben/ben shock.png
Normal file
After Width: | Height: | Size: 353 KiB |
BIN
game/dev/old/ben/ben unimpressed.png
Normal file
After Width: | Height: | Size: 286 KiB |
BIN
game/dev/old/damien/damien angry.png
Normal file
After Width: | Height: | Size: 326 KiB |
BIN
game/dev/old/damien/damien considering.png
Normal file
After Width: | Height: | Size: 315 KiB |
BIN
game/dev/old/damien/damien explanatory.png
Normal file
After Width: | Height: | Size: 320 KiB |
BIN
game/dev/old/damien/damien happy.png
Normal file
After Width: | Height: | Size: 304 KiB |
BIN
game/dev/old/damien/damien neutral.png
Normal file
After Width: | Height: | Size: 302 KiB |
BIN
game/dev/old/damien/damien sad.png
Normal file
After Width: | Height: | Size: 302 KiB |
BIN
game/dev/old/damien/damien shock.png
Normal file
After Width: | Height: | Size: 322 KiB |
BIN
game/dev/old/damien/damien unimpressed.png
Normal file
After Width: | Height: | Size: 322 KiB |
BIN
game/dev/old/inco/inco angry.png
Normal file
After Width: | Height: | Size: 291 KiB |
BIN
game/dev/old/inco/inco annoyed.png
Normal file
After Width: | Height: | Size: 286 KiB |
BIN
game/dev/old/inco/inco confused.png
Normal file
After Width: | Height: | Size: 286 KiB |
BIN
game/dev/old/inco/inco considering.png
Normal file
After Width: | Height: | Size: 291 KiB |
BIN
game/dev/old/inco/inco happy.png
Normal file
After Width: | Height: | Size: 286 KiB |
BIN
game/dev/old/inco/inco sad.png
Normal file
After Width: | Height: | Size: 291 KiB |
BIN
game/dev/old/inco/inco shock.png
Normal file
After Width: | Height: | Size: 291 KiB |
BIN
game/dev/old/inco/inco smug.png
Normal file
After Width: | Height: | Size: 288 KiB |
BIN
game/dev/old/inco/inco wtf.png
Normal file
After Width: | Height: | Size: 269 KiB |
BIN
game/dev/old/liz head/liz head angry.png
Normal file
After Width: | Height: | Size: 80 KiB |
BIN
game/dev/old/liz head/liz head happy.png
Normal file
After Width: | Height: | Size: 81 KiB |
BIN
game/dev/old/liz head/liz head sad.png
Normal file
After Width: | Height: | Size: 77 KiB |
BIN
game/dev/old/liz/liz angry.png
Normal file
After Width: | Height: | Size: 382 KiB |
BIN
game/dev/old/liz/liz considering.png
Normal file
After Width: | Height: | Size: 341 KiB |
BIN
game/dev/old/liz/liz explanatory.png
Normal file
After Width: | Height: | Size: 392 KiB |
BIN
game/dev/old/liz/liz happy.png
Normal file
After Width: | Height: | Size: 380 KiB |
BIN
game/dev/old/liz/liz neutral.png
Normal file
After Width: | Height: | Size: 335 KiB |
BIN
game/dev/old/liz/liz sad.png
Normal file
After Width: | Height: | Size: 289 KiB |
BIN
game/dev/old/liz/liz shock no head.png
Normal file
After Width: | Height: | Size: 352 KiB |
BIN
game/dev/old/liz/liz shock.png
Normal file
After Width: | Height: | Size: 411 KiB |
BIN
game/dev/old/liz/liz unimpressed no head.png
Normal file
After Width: | Height: | Size: 312 KiB |
BIN
game/dev/old/liz/liz unimpressed.png
Normal file
After Width: | Height: | Size: 354 KiB |
BIN
game/dev/old/lizhead/lizhead angry.png
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
game/dev/old/lizhead/lizhead happy.png
Normal file
After Width: | Height: | Size: 79 KiB |
BIN
game/dev/old/lizhead/lizhead sad.png
Normal file
After Width: | Height: | Size: 75 KiB |
BIN
game/dev/old/lizhead/lizhead shock.png
Normal file
After Width: | Height: | Size: 96 KiB |
BIN
game/dev/old/mia/mia angry.png
Normal file
After Width: | Height: | Size: 348 KiB |
BIN
game/dev/old/mia/mia considering.png
Normal file
After Width: | Height: | Size: 334 KiB |
BIN
game/dev/old/mia/mia explanatory.png
Normal file
After Width: | Height: | Size: 357 KiB |
BIN
game/dev/old/mia/mia happy.png
Normal file
After Width: | Height: | Size: 340 KiB |
BIN
game/dev/old/mia/mia neutral.png
Normal file
After Width: | Height: | Size: 330 KiB |
BIN
game/dev/old/mia/mia sad.png
Normal file
After Width: | Height: | Size: 343 KiB |
BIN
game/dev/old/mia/mia shock.png
Normal file
After Width: | Height: | Size: 415 KiB |
BIN
game/dev/old/mia/mia unimpressed.png
Normal file
After Width: | Height: | Size: 403 KiB |
BIN
game/dev/old/olivia dad/olivia dad neutral.png
Normal file
After Width: | Height: | Size: 352 KiB |
BIN
game/dev/old/olivia/olivia angry.png
Normal file
After Width: | Height: | Size: 361 KiB |