From 2d7dbe74f17c7d0d79bee4177981e3216abcfe42 Mon Sep 17 00:00:00 2001 From: Hersi Date: Fri, 10 Nov 2023 07:55:55 +0100 Subject: [PATCH] Fix usernames on several user interface panels --- docs/lua_api/challengeresult.lua | 121 ++++++++++++++++++++++++ docs/lua_api/result.lua | 73 +++++++------- scripts/challengeresult.lua | 5 + scripts/gameplay/user_panel.lua | 8 +- scripts/result.lua | 16 ++-- textures/result/default_appeal_card.png | Bin 0 -> 14954 bytes textures/result/default_dan.png | Bin 0 -> 4895 bytes 7 files changed, 182 insertions(+), 41 deletions(-) create mode 100644 docs/lua_api/challengeresult.lua create mode 100644 textures/result/default_appeal_card.png create mode 100644 textures/result/default_dan.png diff --git a/docs/lua_api/challengeresult.lua b/docs/lua_api/challengeresult.lua new file mode 100644 index 0000000..335a311 --- /dev/null +++ b/docs/lua_api/challengeresult.lua @@ -0,0 +1,121 @@ +-- challengeresult `result` table + +---@diagnostic disable:lowercase-global +---@diagnostic disable:missing-return + +---@class ChallengeHitStat +---@field timeFrac number -- Fraction of when in the chart the note was hit, `0.0` to `1.0` +---@field lane integer -- `0` = A, `1` = B, `2` = C, `3` = D, `4` = L, `5` = R, `6` = Left Laser, `7` = Right Laser +---@field time integer -- When in the chart the note was hit, in milliseconds +---@field delta integer -- Delta value of the hit from 0 +---@field rating integer -- `0 = Miss`, `1 = Near`, `2 = Crit` + +---@class ChallengeHitWindow +---@field good integer # Near window, default `92` +---@field hold integer -- Hold window, default `138` +---@field miss integer -- Miss window, default `250` +---@field perfect integer -- Critical window, default `46` +---@field slam integer -- Slam window, default `84` +---@field type integer -- `1 = Normal` default, `2 = Hard` default values halved + +---@class ChartResultScore +---@field auto_flags integer # Autoplay flag +---@field badge integer # `0` = Manual Exit, `1` = Played, `2` = Cleared, `3` = Hard Cleared, `4` = Full Chain, `5` = Perfect Chain +---@field combo integer # Best combo reached +---@field earlies integer # Total early hits +---@field gauge number # Ending gauge percentage, `0.0` to `1.0` +---@field gauge_option integer # Gauge option e.g. ARS +---@field gauge_type integer # `0` = Normal, `1` = Hard, `2` = Permissive, `3` = Blastive +---@field goods integer # Total near hits +---@field hitWindow ChallengeHitWindow # Hit windows of the score +---@field lates integer # Total late hits +---@field mirror integer # Mirror mode flag +---@field misses integer # Total errors +---@field perfects integer # Total critical hits +---@field random integer # Random mode flag +---@field score integer # Result score +---@field timestamp integer # Unix timestamp of the score + +---@class ChartResult +---@field artist string # Chart artist +---@field autoplay boolean # Autoplay bool, always false +---@field auto_flags integer # Autoplay flag +---@field badge integer # `0` = Manual Exit, `1` = Played, `2` = Cleared, `3` = Hard Cleared, `4` = Full Chain, `5` = Perfect Chain +---@field bpm number # Chart BPM +---@field difficulty integer # Difficulty index +---@field duration integer # Chart duration, in milliseconds +---@field earlies integer # Total early hits +---@field effector string # Chart effector +---@field failReason string # Reason for failing the chart +---@field gauge number # Ending gauge percentage, `0.0` to `1.0` +---@field gaugeSamples number[] # Gauge values sampled (256 total) throughout the play +---@field gauge_option integer # Gauge option e.g. ARS +---@field gauge_type integer # `0` = Normal, `1` = Hard, `2` = Permissive, `3` = Blastive +---@field goods integer # Total near hits +---@field grade string # Result grade +---@field highScores ChartResultScore[] # All scores +---@field hitWindow ChallengeHitWindow # Result hit windows +---@field illustrator string # Chart jacket illustrator +---@field isSelf boolean # Always true +---@field jacketPath string # Full filepath to the jacket image on the disk +---@field lates integer # Total late hits +---@field level integer # Chart level +---@field maxCombo integer # Result max chain +---@field meanHitDelta number # Mean hit delta +---@field meanHitDeltaAbs number # Absolute value of mean hit delta +---@field medianHitDelta integer # Median hit delta +---@field medianHitDeltaAbs integer # Absolute value of median hit delta +---@field mirror boolean # Mirror mode bool +---@field misses integer # Total errors +---@field mission string # Always empty string +---@field noteHitStats ChallengeHitStat[] # Hit stats for every chip hit +---@field passed boolean # Chart passed +---@field percent integer # Chart challenge percent +---@field perfects integer # Total critical hits +---@field playbackSpeed number # Always 1.0 +---@field random boolean # Random mode bool, +---@field realTitle string # Chart title, always without player name +---@field retryCount integer # Always 0 +---@field score integer # Result score +---@field speedModType integer # `0` = XMOD, `1` = MMOD, `2` = CMOD +---@field speedModValue number # `HiSpeed` for `XMOD`, `ModSpeed` otherwise +---@field title string # Chart title + +---@class ChallengeResult +---@field avgCrits integer # Average number of critical hits across the charts +---@field avgErrors integer # Average number of error hits across the charts +---@field avgGauge number # Average gauge percentage across the charts +---@field avgNears integer # Average number of near hits of the charts +---@field avgPercentage integer # Average completion percentage across the charts +---@field avgScore integer # Average score across the charts +---@field badge integer # `0` = Manual Exit, `1` = Played, `2` = Cleared, `3` = Hard Cleared, `4` = Full Chain, `5` = Perfect Chain +---@field charts ChartResult[] # array of result information for all played charts (note: might not be all charts in course) +---@field failReason string # Reason for failing the challenge +---@field grade string # Result grade +---@field isSelf boolean # Always true +---@field level integer # Chart or challenge level +---@field overallCrits integer # Total number of critical hits across the charts +---@field overallErrors integer # Total number of error hits across the charts +---@field overallNears integer # Total number of near hits across the charts +---@field passed boolean # Whether or not the challenge was passed +---@field requirement_text string # The challenge requirements separated by newline character `"\n"` +---@field title string # Challenge title + +---Render, called every frame +---@param deltaTime number # time in seconds between frames +---@param showStats boolean # true when left FX is pressed +render = function (deltaTime, showStats) end + +---This is called right after result is set, either for initial display or when the player whose score is being displayed is changed. +result_set = function () end + +---The region of the screen to be saved in score screenshots. +---@return number x # top left X coordinate +---@return number y # top left Y coordinate +---@return number w # width +---@return number h # height +get_capture_rect = function () end + +---Called when a screenshot has been captured successfully. +---@param path string # path to the saved screenshot +screenshot_captured = function (path) end diff --git a/docs/lua_api/result.lua b/docs/lua_api/result.lua index aa17fb9..7af03a7 100644 --- a/docs/lua_api/result.lua +++ b/docs/lua_api/result.lua @@ -1,4 +1,7 @@ --- result and challengeresult `result` table +-- result `result` table + +---@diagnostic disable:lowercase-global +---@diagnostic disable:missing-return ---@class HitStat ---@field timeFrac number -- Fraction of when in the chart the note was hit, `0.0` to `1.0` @@ -7,7 +10,6 @@ ---@field delta integer -- Delta value of the hit from 0 ---@field hold integer -- `0` for chip/laser, otherwise `# Ticks` of hold ---@field rating integer -- `0 = Miss`, `1 = Near`, `2 = Crit` -HitStat = {}; ---@class HitWindow ---@field good integer # Near window, default `92` @@ -16,7 +18,6 @@ HitStat = {}; ---@field perfect integer -- Critical window, default `46` ---@field slam integer -- Slam window, default `84` ---@field type integer -- `1 = Normal` default, `2 = Hard` default values halved -HitWindow = {}; ---@class Score ---@field auto_flags integer # Autoplay flag @@ -25,21 +26,25 @@ HitWindow = {}; ---@field gauge_option integer # Gauge option e.g. ARS ---@field gauge_type integer # `0` = Normal, `1` = Hard, `2` = Permissive, `3` = Blastive ---@field goods integer # Total near hits ----@field hitWindow HitWindow|nil # Hit windows of the score, only for singleplayer results screen +---@field hitWindow HitWindow # Hit windows of the score ---@field mirror integer # Mirror mode flag ---@field misses integer # Total errors ----@field name nil|string # Only for multiplayer results, name of the player ---@field perfects integer # Total critical hits ---@field random integer # Random mode flag ---@field score integer # Result score ---@field timestamp integer # Unix timestamp of the score ----@field uid nil|string # Only for multiplayer results, UID of the player -Score = {}; ----@class ChartResult : result ----@field passed boolean # Whether or not challenge requirements were met for this chart ----@field failReason string # Fail reason if a challenge requirement was not met -ChartResult = {}; +---@class MultiplayerScore +---@field badge integer # `0` = Manual Exit, `1` = Played, `2` = Cleared, `3` = Hard Cleared, `4` = Full Chain, `5` = Perfect Chain +---@field flags integer # Autoplay flag +---@field gauge number # Ending gauge percentage, `0.0` to `1.0` +---@field goods integer # Total near hits +---@field misses integer # Total errors +---@field name string # Name of the player +---@field perfects integer # Total critical hits +---@field score integer # Result score +---@field timestamp integer # Unix timestamp of the score +---@field uid string # UID of the player ---@class ServerScoreOptions ---@field gaugeType integer # An enum value representing the gauge type used. 0 = normal, 1 = hard. Further values are not currently specified. @@ -47,7 +52,6 @@ ChartResult = {}; ---@field mirror boolean # Mirror mode enabled ---@field random boolean # Note shuffle enabled ---@field autoFlags integer # A bitfield of elements of the game that are automated. Any non-zero value means that the score was at least partially auto. -ServerScoreOptions = {} ---@class ServerScore ---@field score integer # Submitted score @@ -63,28 +67,19 @@ ServerScoreOptions = {} ---@field windows table # {perfect, good, hold, miss, slam} hit windows in milliseconds ---@field yours boolean # This score belongs to the current player ---@field justSet boolean # This score belongs to the current player, and is the score that was just achieved -ServerScore = {} ----@class result +---@class Result ---@field artist string # Chart artist ---@field auto_flags integer # Autoplay flag ---@field autoplay boolean # Autoplay bool ----@field avgCrits integer # Only for challenge results, average number of critical hits across the charts ----@field avgErrors integer # Only for challenge results, average number of error hits across the charts ----@field avgGauge number # Only for challenge results, average gauge percentage across the charts ----@field avgNears integer # Only for challenge results, average number of near hits of the charts ----@field avgPercentage integer # Only for challenge results, average completion percentage across the charts ----@field avgScore integer # Only for challenge results, average score across the charts ---@field badge integer # `0` = Manual Exit, `1` = Played, `2` = Cleared, `3` = Hard Cleared, `4` = Full Chain, `5` = Perfect Chain ---@field bpm number # Chart BPM ----@field charts ChartResult[] # Only for challenge results, array of chart results ---@field chartHash string # Chart hash ---@field difficulty integer # Difficulty index ---@field displayIndex nil|integer # Only for multiplayer results, the index of the score being viewed ---@field duration integer # Chart duration, in milliseconds ---@field earlies integer # Total early hits ---@field effector string # Chart effector ----@field failReason string # Reason for failing the challenge ---@field flags integer # Gameplay option flags e.g. gauge type, mirror/random mode ---@field gauge number # Ending gauge percentage, `0.0` to `1.0` ---@field gauge_option integer # Gauge option e.g. ARS @@ -92,7 +87,7 @@ ServerScore = {} ---@field gaugeSamples number[] # Gauge values sampled (256 total) throughout the play ---@field goods integer # Total near hits ---@field grade string # Result grade ----@field highScores Score[] # All scores +---@field highScores (Score|MultiplayerScore)[] # All scores ---@field hitWindow HitWindow # Result hit windows ---@field holdHitStats HitStat[]|nil # Hit stats for every hold object, only available for singleplayer if `isSelf = true` ---@field illustrator string # Chart jacket illustrator @@ -103,7 +98,7 @@ ServerScore = {} ---@field jacketPath string # Full filepath to the jacket image on the disk ---@field laserHitStats HitStat[]|nil # Hit stats for every laser object, only available for singleplayer if `isSelf = true` ---@field lates integer # Total late hits ----@field level integer # Chart or challenge level +---@field level integer # Chart level ---@field maxCombo integer # Result max chain ---@field meanHitDelta number # Mean hit delta ---@field meanHitDeltaAbs number # Absolute value of mean hit delta @@ -113,20 +108,34 @@ ServerScore = {} ---@field misses integer # Total errors ---@field mission string # Only for practice mode ---@field noteHitStats HitStat[]|nil # Hit stats for every chip hit, only available for singleplayer if `isSelf = true` ----@field overallCrits integer # Only for challenge results, total number of critical hits across the charts ----@field overallErrors integer # Only for challenge results, total number of error hits across the charts ----@field overallNears integer # Only for challenge results, total number of near hits across the charts ----@field passed boolean # Only for challenge results, whether or not the challenge was passed ---@field perfects integer # Total critical hits ---@field playbackSpeed number # Only for practice mode, percentage from 0.25 to 1.0 ---@field playerName nil|string # Only for multiplayer ---@field random boolean # Random mode bool, ---@field realTitle string # Chart title, always without player name ----@field requirement_text string # Only for challenge results, the challenge requirements separated by newline character `"\n"` ---@field retryCount integer # Only for practice mode ---@field score integer # Result score ---@field speedModType integer # Only for singleplayer, `0` = XMOD, `1` = MMOD, `2` = CMOD ---@field speedModValue number # Only for singleplayer, `HiSpeed` for `XMOD`, `ModSpeed` otherwise ----@field title string # Chart (with player name in multiplayer) or challenge title ----@field uid nil|string # Only for multiplayer, UID of the player -result = {}; +---@field title string # Chart (with player name in multiplayer) +---@field uid nil|string # Only for multiplayer, UID of the __viewer__ +result = {} + +---Render, called every frame +---@param deltaTime number # time in seconds between frames +---@param showStats boolean # true when left FX is pressed +render = function (deltaTime, showStats) end + +---This is called right after result is set, either for initial display or when the player whose score is being displayed is changed. +result_set = function () end + +---The region of the screen to be saved in score screenshots. +---@return number x # top left X coordinate +---@return number y # top left Y coordinate +---@return number w # width +---@return number h # height +get_capture_rect = function () end + +---Called when a screenshot has been captured successfully. +---@param path string # path to the saved screenshot +screenshot_captured = function (path) end diff --git a/scripts/challengeresult.lua b/scripts/challengeresult.lua index 533ee17..506bf92 100644 --- a/scripts/challengeresult.lua +++ b/scripts/challengeresult.lua @@ -7,6 +7,11 @@ local Sound = require("common.sound") local Numbers = require('components.numbers') local VolforceWindow = require("components.volforceWindow") +-- Lua code completion annotation + +---@diagnostic disable-next-line +---@cast result ChallengeResult + -- Window variables local resX, resY diff --git a/scripts/gameplay/user_panel.lua b/scripts/gameplay/user_panel.lua index 1b8b997..d20815c 100644 --- a/scripts/gameplay/user_panel.lua +++ b/scripts/gameplay/user_panel.lua @@ -1,4 +1,4 @@ - +require("common.gameconfig") local VolforceWindow = require('components.volforceWindow'); local desw = 1080; @@ -13,7 +13,9 @@ local danBadgeImage = gfx.CreateSkinImage("dan.png", 0); local idolFrameImage = gfx.CreateSkinImage("crew/frame.png", 0); -local username = game.GetSkinSetting('username') or ''; +-- gameplay table does not have a current username field, because why would it lmao +-- workaround: retrieve it directly from Main.cfg file +local username = GameConfig["MultiplayerUsername"] or game.GetSkinSetting('username') or ''; local drawBestDiff = function (deltaTime, score, bestReplay, y) if not bestReplay then return end @@ -138,4 +140,4 @@ end return { render=render -} \ No newline at end of file +} diff --git a/scripts/result.lua b/scripts/result.lua index 40a6540..d5e1b89 100644 --- a/scripts/result.lua +++ b/scripts/result.lua @@ -48,6 +48,8 @@ local defaultJacketImage = gfx.CreateSkinImage("result/default_jacket.png", 0); local bestScoreBadgeImage = gfx.CreateSkinImage("result/best.png", 0); +local defaultCardImage = gfx.CreateSkinImage("result/default_appeal_card.png", 0) +local defaultBadgeImage = gfx.CreateSkinImage("result/default_dan.png", 0) local appealCardImage = gfx.CreateSkinImage("crew/appeal_card.png", 0); local danBadgeImage = gfx.CreateSkinImage("dan/inf.png", 0); @@ -166,7 +168,7 @@ local BOTTOM_PANEL_TRANSTION_ENTER_OFFSET = 256; local highScore; -local username = game.GetSkinSetting('username'); +local username = GameConfig["MultiplayerUsername"] or game.GetSkinSetting('username') or ''; local msg = game.GetSkinSetting("MSG"); local earlyLateBarsStats = { @@ -545,25 +547,27 @@ local drawBottomPanelContent = function(deltatime) -- Draw appeal card gfx.BeginPath(); gfx.ImageRect(bottomPanelX + 58, bottomPanelY + 277, 103, 132, - appealCardImage, 1, 0); + result.isSelf and appealCardImage or defaultCardImage, 1, 0); -- Draw description gfx.FontSize(22) gfx.LoadSkinFont('Digital-Serial-Bold.ttf') gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE) - gfx.Text(msg, bottomPanelX + 190, bottomPanelY + 282); + gfx.Text(result.isSelf and msg or ("Player "..result.displayIndex), bottomPanelX + 190, bottomPanelY + 282); -- Draw username gfx.FontSize(28) - gfx.Text(username, bottomPanelX + 190, bottomPanelY + 314); + gfx.Text(result.playerName or username, bottomPanelX + 190, bottomPanelY + 314); -- Draw dan badge gfx.BeginPath(); gfx.ImageRect(bottomPanelX + 187, bottomPanelY + 362, 107, 29, - danBadgeImage, 1, 0); + result.isSelf and danBadgeImage or defaultBadgeImage, 1, 0); -- Draw volforce - VolforceWindow.render(0, bottomPanelX + 310, bottomPanelY + 355) + if result.isSelf then + VolforceWindow.render(0, bottomPanelX + 310, bottomPanelY + 355) + end -- Draw IR text gfx.FontSize(22) diff --git a/textures/result/default_appeal_card.png b/textures/result/default_appeal_card.png new file mode 100644 index 0000000000000000000000000000000000000000..1d125351118922ad25bc0fc2f819a7c745114e12 GIT binary patch literal 14954 zcmV-wI+ewVP)soqLn2sHp${{{aF4`S|)JB3A6|?H(LOZ*FfmEGsB1 zZ8$Jx3JC}j5+^b%D)RC24GR@WM@i-7<}o#RJ2!CH*w-*BT@)A+EGuOuCt)NaC;ujV z;NapN88svy8%rloNgYWpAx|$DL}E2!n~S?OH8hckza<3}MMYK~B5G4MV@)huJ~lcd zAw1C7;u#ks8UznPK6ge(i8CW9S}RvmN`ji2oIOB-Iv`1`rKw6iZfHPlT0Cuxl9yXj zj4Bg5T}F3%e11|BKo<=hcy)I>FGNH)Q7gM>*#eN-PzD?oLmP8pphkK(?MsrXrIe&POYh$4{ zHdkg{m26gtMm=N_6gDIeB!_&qd~Tjp1TiiWF1NY8dQpEl8##7hm0ej@Kt4h|GcZOf zGer$G|GxfHJXo)(%o`tHT3DKGYKT}%W4yT3#>3xhVrGP2j3z61UR-6&x5H{aQ0$=U z6BtpNj>x#Mxwdqt_yu|PBzOC(`G}vV|Ihzp2Q+{|W2B+CH3c6&Dlt1Yz6R`K|6 zc{@8;M@elPbhjG+b@Aj?#2svUDBbUfv9`Whua|pxgVJ+jfu`FUm~yaEEJ_)fth$uf zEw%m$pxxs3a@VJ_Tb}p)ZJ~(b-har-kVpz)i5-jt z1qD$9z8OetaFX^#aHs)WgDqJQK`06ewzgXzr1&8A4;br{FG>gg9o{7ErXnKvpoe>V zzU14=;hxjGYxnNmdv^U-*aMPw?cVq7*pZ*GeC%K1{`cIGn$wwA;C9;Ur z(fcGK5Fm4Y3hX=<0S?efonM&UC4kfHFOvJ@6u5j}sOyIWnsdwqmAITTu`xJ|^p{Q0Bz zr?QsLo_Kch0L%}B5UOkv>0xI$A_&4(mWU$1#S8#IgDdQ~b~K{2$7Tr((I zRxtp=&MhoooXR3m=2_}8m?_IL!$4)3$Bl*}%SL0UbUK>W01QUgM8goZ!S(B-({ut& zi(8{NK4095F}cTU%Em-d6itIxwh^|f>!bB5z<S`hRXJ-8VK_INo#9&A8Zxthwa~5O@fcnPdw>MK*@G+`*f}078YxGJzZi5o;FL=-?)$;xvSc znkOg&*M)iF;RZh5%BOh-IT}ffH*iNI2+c_dBIcqOT@H19q*rgCAVjLaf-501f67)7 zVfU9#BqmOQgM&8olx}K|2hO08*azM^^6Asso9m51>xx6uhCx#zP0=(((Ud^Z+TFbNxjPC#w~tuQ+7i(HV!t{H;{~z3C$L+$$=S3r>0~niF+gTSChUo< zteRq$JbjwXT$xWZ;=E49V{&*$=V45R@->0iDYm@I3fCxB6iX$M7FJhT>I@~Uo{5Kc z28LE#@$GVpyW3J~FI)}<-4(%m{h~WUj?d!m_tWCACE~<1TLgwsnu$Y|WoFqTL>0*l zQh^wtt0pc^Lq(B#Aw%*Md5zV{0!5Z3J;&Bahs|VIc$!fzCm5sw5fdC#^RJ=4gM#`T zQViWykm*-YeT49K1-WjLtuV>f5iEtpvhXw5>k2bl@Ic9F$4xN-MTy^8SSauXwg46u zSb!u@l0*p-JB6_0B-lvPUe|8*>40ssL9ed$+rIC$eUB~HJ=e9MtnCGHb_q+e#ht<0 z{>Su8&yFnlJ6TtMkX49e)n>A!NY|yKM;`z|{Ui&Z8S5Txv|2*%so)B33znAezw)cE zw3aV~it8#nvTo(`3m_{W$->E=_`QiTvu)y4Fj2(k`FSvr)cM4{61c~Mdq*;*T5kD5 zK0{qf0Uq(S+#i zOuU^t8fEKPBn#PX2~RUw6|z1h$hyifYF3ozMaVj=gsYS;@}kc3dbw1-Rw!IslorcU zsa(5I(_f}yyrkf1aZzH+HK|;N-+{nJKLDL(S6I!)X$?1pO2zXlmGu_aY9Vc1E4nTh zC;^uwe-m3?IC^^~>k#Aj(qP*usD#8*iFZ&5W_bdXN>C*UaNz z>gse_JfDG;pvPk>=S!tI7|ikoY3^>td6t^uZRTzTUf!LHrX|%5*QDvXn0x!Ad#~+L zi@k?;D!sca>joZ-UaV*wOsi-rK}3P|C5P?JVcRBtH;W;P2Jeh^*^905^-J)2xTZI&q3QHAIE*YRyN~FjaJPs zar1HXM4Dah)`9O>Ad&Fx|6^-@U*VQYE_0ss;NZ&15Ke!DkfA84uDBb%o^Eows_H6= z*OixIdj3`JWnF){@M0d|@a*NgSz+#}1_`1w3kO{ud^rG%&C$a>TN7vJ7bw_D5g=G_ z$HH;o;I?Z5+2VPH7kLxelEj*-!m({#w}qy!PnKZYo-NgFm%y1E$2^;>tHMH4*Pp$p zzW_kgUpzfB3VxbI0ZP4f^9a3|^!7wgv$-FE`;)sue{8+VQ)f*XhYfGvjHe2P zXwf5sq>M?@m{~GIx*e)nwZoRU+c%_LvZaS?3#Mhy2>OhonhD^9%+XOg9W67Js9Lve zuAJ4FY&ln0jzC{5!F7R%x> z)*-_1iN?B=W7*BO@DHyj``>AGce+f2ie_&eF}+hLMrA zEt*q3PSD_qq0<_ZbNw)y!7v8+slXd0;zVHgO*^)b}6lwwu?@kA1PqvTDLZJzwPH6rE00(gwxQE+81HoGTNWMwOW|5mn`=Qu=Sto zDwd3t(|JOp9YAQBcfqnu77Of-9PEX77WX49rwA%+?6lini0w}Ij3`YF^!sY{9DM(u z);F!A1K&kwrw~P0{`qtgM7v`8q-k0pF|)kb;4$1E!yQ13@Ih{E-IFM4yw}M(joV7&36a>>0O{f*(ghA7WMmvBo821KXj7s2I-(o{zF+WE5 zJwT8c&SKeM3|nk(``UQ3xzmX%QZXL9LHtgsEC51h)Frg8x!e?JWW>&+CXEfFa`j^;l#jV=<1%u(>x&q%u`X-7y zr6W5b!vQ^9+18Nj5lcYJgdjq_c#cn|y@Dla1{DmBBlI7e-n8J}^AnUm)&oR18w-v{ zf^226Gj)%iE-FWq)KHbS-X6XWSI+pZoT#ZqSx}-$KAPu^2m(aX1q6)%K{$Z8KRFp% z?v`WAxsc%)!G@{Su^4sw7*$E;Bh#6vyjMxB@(t+c`@xuo5mB2Q{Nbh?t*Ox>bW7n= zuukF4!=3qR}k10zt^$MG;b9!7vTbo|({L%|GmeQJ8@$W(33 zz%YLP`njU5ttU@z8oUKmQ&mk5boiML&1dz{L}Vn~00<`lVqAp) zF%5vY<4M`{w0HqyGds|%7GQoJRSSwHRm&0x_tTgAPPG{`6G%kFPhorj?0M zR7Zg$)2Lb`s+J3?^@>!j$3#wysHdl;YQ3kKm6~|}-?W8^p_7#5_1ZyNw6`OPB|iU0 zeyM9(6pn{G?)dyXDXNQfLNwI{^77QKS88A*rl$cA1DYF~Y0ayoBM29*+8_Z!2Y}E` zguE^z%WB;5&`0fh-dX#N+J3ZKTAOPMJTiN#?Kf||eT59Uo^~7Ga2jWvAvCd#<1^an zJ5(2#qf1vSVCmH|#q3kJraRLbZl>iK(xS8ifr+4)R>&Q~)SGY_=*vCBqTw@=x8<3Wsqj62@Eid|wxY%VST&Xmm=WaeNxR z#=B$gx%Vrh+ZUN5c=>;%&TJv-1|t^R)W8R~~>^-IRUvjiS<#Te_V@07N()#?P+Z)abowhnpSX-Y|}l z#*kBlJ(}33Yd23+s+Zu4E;xxMg(lahXa|J$BrP?hHH1xAZNUj0N-GxHLumz1(z+4n zbD4Z5M^To@zh?!v<+jAMa_0+;w2XV_-*&aq8XwcoKw81d3oq7Yv>O$b`r?cCw~P&> zC3R44fDS4RhDHxTimpL#9}hY5~!lcd{Cj=SK+)b!Z&$lc6#jrryR!yHv>BWi^L_8|Ta z2m^YyP^>!`e#=za z)!zqz7$fyYGNf{ksnC-~jggs(Rro?2X3z^V1=@pXHnAT8Vp!fkWRT0Tq0<=V8L|ap zHgCXTXB`BwM@Nawjp*D*d9#^^YVl?&-nEG(D=r93#m@f*gZa z#PFJUE_l6InXWLf#&Gp2vr!TEAX?fQMszTsz)<{6TG1$v&RsrP%M~NZ}^| z?D_$vwIAkEDURbh#D(2mEMD=9F^zydi1a@I!l0edp_2&yFKBXjk%`w3#C=(Rb^+YL zGk!%Hks+_hQQ`EduBJJ+CZ0smNNk+}uw+NM)WSgO4ULo3gvgVVXuYRWx%7IaYTDS) zUtp?w#lmP`YbI(%K=fuWc_=tmA+f}BqBpDf&dZT z>i&qa1%Swfaq*IZ(YV46a4EMXl?}1rZ%DT>0S`cqpxP7DK5@PJA;WwK-1<ve$Gz{>3qmle--)73kr=W`v z5+s}uiG*Vu8^dCE*REWbn)s5!lx|i_EguFz$VY|@^H<(^c^=aRW8Q$rYj-;c)}TcRja8k-K~~=QlJN) z7*?s3{Rj|R@8S0Pu&vdKETy;dXAvMWc||(eun%3FU<3hT z4TlT0_Rwl%G{XZRvKo@sxM;UN;ndF*Yx+-$`t9Pj>h6l{0&_tR#^#weK*)#Hkd}G~ zQ>(d0w3m0cj|=N>Uz-dimK_W6xMeRIhBQv`=1k5k0wUYv97>>X0D{MFhpwKbc}q4$ zx@gV?uUcjtPGjiD$_t+qU#J$3E{)eN9Kn-@LbKK~HqgLfrP81r#D;b2!v4M23I|iW zCI8gqa)SIF4v9(h@GW|Ki%2k=`77z-k`@^ zEa`HwS8By#tx~L18K!!K0P)g7%h=3IfKbbv2ls3*9?CMis*8o6O`O-b5VdIHapP9Q z-JM+kKy3LQ`uj1w{no#G!N+L?2wKr7ZCEqFgSI%$C$frfpP%b$F9pFAMc@`Lpw>!I#TIxm+e}M4TX^QTwTuNB8;S{*}LHu$fFQ{S)d_ zspMv};b&-$=V*>2Nt$#ZBjJp}sJ_k=nGFU^1Omi;ZN>)Z0ORMgGKx~ETo(4Pl?6d4 z>`o!`;9t(STZ5I=TmPY7JZ0vkY&&bXy3%emKIM?O8q#7}rz7xmyR>fWFgEkZ|Gg$0 ztLo+F)d$D=ec^$(3qNawlF=Q_-bchCj~?sg4>rYiJOT<~m{y!u!;-Y)HHwW<2WQu*TX;`&8F$OfW&7JF|PEb&|6d}gor zjhh^8;W)R2OGrjy&X~Z|*5hwp|KyX`pSU=$?Jzbkc=>Sc=8$k~Dhsc9{IPUjuef2r90qOW(&o%dJ#SVR z>D1^#++t!uTlSD1OX!V`8P(jJYyz8*NeiB>QLTLUGok$ZzO7y#)ER8$(!IMvd9hF; zmWeYxi{Am7-}*G!hOl5)KE3B{0})I6a5Wofh{XT4@=SZz}fz z4}+I4D{abagj@UiLm8G}mZi$PR9> z(L@z$qO{=IlDtxV*ZK9gOY3)xdEZrg2d(u&{ZJ@mg_DF6gq!h8IUy=h{% zB;u@#q+Kz4Y$oBD2|9ukbMV>&vp$IyJX?SmR4VV~%8QHT!QI8u!NIlE2L+)}CW*-Eb-z7x~ib&9_KCDJn~(3V|%(g<{F3oUrIMm3l~!=TdOjoOq`rSjyiuvnU$ zJa-QC{(ruOYjw&P6mc>UKwb~L~Ea#}_TPw~h`gWIUt1;j;QBYg5&rmja zf?po55^)+y#3EKpBM0JeUU3;r8nrtSsdu6bPisaf`yfo3K-g_GWkW25c$VcP5p`Fb zXB-S*fxyq5M1a~Y%ffC-C^t5kmQg1Vf|cd0U6mE*88vyBV@Hbuv0Fno8BtW()ukYP53CfQQ(v)%SDC%p|p}4q6>SUQ@^(Rr7F3_ssI2Oe<}FQp_Y z7E8s#uv`p#*@U?c^zMHn#pSu{J+5fp8+gM*Mn z1dwG4z%bi3(!v5kKx4xo8VdyCI8l`R{!}W6ho<3BJN!${u#9McqZFF|HMl27)`kv# z?4E3Hm~3cH4lNChB;og(o0HA$p-@LhyV{txw8MzwqmK6n_p}p8kr5?Olps*GwK`f_ z8wg2c)Dg24ajs};hbx$ZJ*d4;#KK*D$wNDnNp-~RRs$?5Ane}|T8rWH{X>6rrjLH! z>25sRNZJwM6$c1}l1gk2rtoG@SIYhI zL0CWZ_8#o+?S|Xwxr6RQ+u^S2hOM7u!+sd>R=Jz^H%}fuGTA)QI&%2Oq2yC5%inyn zwtQ@P?b!C-*`4jlzP@C7XGgGg*S>xC!m+7)hh=uK^YGw6=YgS}5pbw56d3HB7CkMK z)V6ZDW%$1rRIG$u5gi!51NU zFYXx}VyL1#fIcufT6V(YAr#g|kTgT_Nai`jO8yopat|;ni|~%!rcI}FaRWg z7RW-G)eDEaFE0F@rjBs1yF4AC{38brT+`CAXU{A`f`agdFBt4wNxmz9a!mj?eEm6;3TFeKY;wH7*3zOqIgmJqVe9+>eX+J zhMuwpkjXqUV4!4^4>=);sz8)$%iyT$KeakH+5 z9@Mk(Guj0jolMS$7E7#>XY!?Dy12E(s@E@qKqMjoQ4!GL(Ev8iKnDS)BM=B3t<}{G zn$LJL8ENLX49#=e;|Gu`{CBVD2K)@4WY}G)@w@Tj%2KhpH6jBb5yM4R-%N&*$yh_p zKL;azRU-T%fbtK;8K^CU^tGkYI%hdKbIP3Qx7g-Sw()`k@r{BcM>(#3lg28a%5^QT zbhU)@*Ch+z9`9={PA_lYJFGG}ay#hsMyV9Zhy&K28mCbAdJUfk1zv4=;KCc+D2r@Y9 zoEE)6XtX>tGpo6CGZ?GCWlK#2;Ko8pb-%b4PK8E>mX?+Zw8D_1@MQ(}n?`G~#A@J- z)>!~jvEK4s+|H^ZuceS>S)_te!C-8tEmsw}ISW1xP zS^>T_u%KIEy{d5r`3!hzmAtaY4y{KQnV~VyeeT(*1C?1jI8GhZK&JN!=V`&(iYZQsFjF1!JLLt9G^G z8?V-I>zQ~y9&XCVAf#lSmlyshqlkV*7G(jkSVtoiWvr!C2d)vE`bAndUU7F_70w?B z1WD5wekPmY`BHUpoNlvVsZ?7B)Xvnc*{+kr8(5v0!cB*UU~u2xmtpNTwXn*iMQLDE zlxS7%+Fo_;r-_WkoH1JL9^XkC?nG!LIKd%u)e0w6y}RLZ9ed`eM(f3nOPfMFwrHu@ z`$Cx&+=8*DuBO;^m&TgvT1rFxt)=a(Dne|Gih@fPoSAQay+Xy{v4yDutfe&c}9i#ap7K>B{YG!P4-cm2!AR0egU**v|uefL1LC1f!$1W!rD7c29-`m7f5W z-?-4=GjrpM*$g>1KB&=JON9%xmf;yt+$xrai>#(_=NON{9yjhjN{h_~#IdFAkQ*r$ zLrb8VLu{1PB~hd0Ik);J{4>UrXYynQk@vE2^5xVqZ%kfeHKNV*KDE{|K!sxq9NU8~Wm<)h-s5V$2U zt&ZswMi4`SLkfy1pmn2!{1_qt*{@M)Z4?F@xVsA=2tr58XwvRP+|oPMmfq*ZN$lUI z*PJgGg(nZcqmj9$ppTtQO4&So`3rs79h-wK)rnwzofN1}NKtqk*Hu~a%vd0LEYa(NZN23vR zA_6)QkXnw7W|e!EzxiN%{Q4Ys=aHbaH=jE4UiP7HRwPE?{0UJCB(l6LN{Iv~DlEPI zN19bwPF6(RA}ET8)W;u7<)$Q|mfGEBNBDIeFJr^re6Z+iMqJIXue(}ppz;PwrVU0B z26M&<0d&G?A`wh3+pax(o57r2ur80kvLMyJdJk>7YVJYn+#9Y1F6!b~t0F-_R)sVB zIN3_1PgytxesZ})#VYVt7YMq*T77K9l$|p9rgEmM;dLEN8SbJ=@9^NjSPVK^J^ff9 z$ewpNAgC>LJ5M)Y5=_)ys zvD52gKhlUoqAatBK`ce#fEWfbx$G^}4^lQaJ)N`ft_5Yl20I*#jONFML$C50Kq4^o z1(tbee0+Hv3{7*vj>S0|dn>cKx$)&J&y@i;Kb>A5`{Qo@kFl}eGl(q$l|e~US06up zT;is))6>&g%2taD3P5atUgaT)CJTv^Xe#Ig%$+SHEd6P(^^HaAj^&px8Gpld<>D>Y zT+X^M_r-&G(xq@w2aj9=4zf$(Bj1g!TYnwM911yeQ)4%}k#bpdhqG$JS2)t?$-^G1VQi#l-Wr|Fp=C> zCl*e>wvhWaw~)=5oKrb70Y+TLX~BW`SAp=5Y8L@H)TI$O5p#2M_%psTHx9rV+yE91 z9B6vWSP6glX*F}&p?+-A6hZBljvxQ(+tbI7pPo7~J82G zAPYk{!bp-{f+oDA`1J>ipVXgSTsSg*tFk!$!LckM@F+s@iooI^2+$BvtkCaY|8;%r z*I&oRe*I&cU_^|UL6Harf$~Nu!ilCH7HoGsay3W=e?mF&+Vu1t*%K^&!xcu|_$^nb z`JVz|BFj2q$2wuMjK?qMU*wdJ4%7EMrfaDeckZu z*d?yt`*2%nr6Z;YWwFAP$Vgc%l-F?ew0R*5Wpp)o^WlZx6NZ~?cNv_Z40bqaG*}3| zKx|h9qTkcg@A35akUa!65=2oa>}o%evDjj-Xss6W{l;_9i>r>E~Q64N>C&A%En0jmOh%0XXSf6;M2FEd49 z9KaWrx6_m3o;tb1oTJWS*dWs&78bG?kzyyYP!_HQ7D!zyH@Os6x<&bsx!6f;gcO6C z@ndnXWTEW*6Tau1J2Q?SPtSQj&F<+uw{N%i?VZd81n|X!O4>q(Ra;-b9`Vi}mAJz@ z_K~`QABWd1v&FeW&kJ*PK9uiQ_mXn5L$m57>#@J;uO-HEokL)knU38ORcvx2m69eg zl5@mG+N~5Y-9%w+z-`Y$ou!|*cjDsb$I}msnD}tW$%7>-=^56IiK_Qq$u`E*DiXR) z20)IT;aF)Q#X1`hG7WNqfZ_v6Xuuu9(H|sgz>>b0v2wsR9TMw`F6Dy@y#oDPp5n9vZ;F{%pw`c^ZQtPPDT&T#%Inx zii#|fTsU$OWylGjHF844zyJl11)R<3CqoNy8FPvp{fLx|6@geH3rIVTjk@FMFq$rl zR(+_WG)RVj1jL?;k1t+*jPGScPN3~JGl1Xo&fh2gMlE1W0R^-}YaG`e^6aR}rg`!5 z<)o^smAzRcgal(1oyj$#!W|7X=jh;JaUGUMYqT#vSqt-Lbyb$-Xf*9%uyVSZ z*sRDN-{FhRz39PJdHw1xw>{(p5ZEQlVi3Eyz!DigIZQrq@PSkoY}RFg)D#&dEu>pw zsj)-`M7JqdMU!JuHHqtT>|Xp_GAxi$FxKNW_pfd_d68t1iFDlzkpb=?p!EVHH2V{k zIcw8)^9{AS^ z&08R_om-UhpIS6pIha;xfS#`r5c~f2_KI8Eo;9?CHLotbbG7XxTNH&UzbBPNvi9DQ zR4lHkg~05#Lf9N_Jn0+)i)#X_g?Rb>>6P1`er!A0$4b9FeRJy5^DB4XT|Q4_Z&HBp zww5ok|4{Rb^)hB{8;AlhMV&6PaG{*40}*1B+XO0zbT}~F;K2|InhMgO(NiWZS~A#R zuu4%8H-s#9F}OoFZN?cg1{+P?Jah=;hxDB!TXvVGB_HS>ev}TSe05U$N9Cl>N$oZG3qe!e67|(ni&L9 zO%V7cGNV+aRsP^inpWwWpu|5SxLKBL;P|nSWPs>AaUN`!cb(dbE0SiCz$E%k3+b9= z))1|N$c!%+E7O)mh}J*|u`KhL<7>9-qA2d+$oAYXGC`ks3RVZCi|;ZuUu03dl~y6rrn)inY{2c8 z>5$6fR-N0o7W}_91jK!DoN7rS;MX{w@_y_r-h*{1iob#B8 zTh{A#FZ7sUh9j_Qv^38%H7y88pZlb%d6A`ZlU$nJwm;?O^wK1XW~z-8lGUo8qp6m1 zNhxh}>L8TU5yfal2h?Vi%79Yp+!un{6o*BYTtjXGbA6)X4Fv=ua!hlWxp@;k@OrjZ zQ!R4T@?t#!hnyM+P3eSo&=}T^H%w|_Fm;MdFlI-nNRUx!K@^NaNgs6=v^oJ#58uSD z*AJep)$|t7^wxIS9*-G~I&|VOx!MSWV~jRfRtr)+XnEL03+>t)(@sv^@wgAwx}}rx zILs-FTpIhiu3sEh%lhYP0i@}z?Z&`Bta>sy>J&y}i5-MC?f}OIq(IAsoneK60WYr} zVc}vx6J&_od)%*2!$)^vbC{yI1!E2V|2|KdrkX6qvPmf!G$?clOS zt{)y^TNOfEK$qjw7W$2jDsMZEbC56P5n1j1gJ2^Qy`7ph@?itt8FfOfC zxM~@vzF|(1(F7}Cb>?=vN3hz|5+wC6*-|VQhk4RWj@PyPzIth2N5{vPuUf{7m-gzd zVN3REBJA_?Ijp*{0y}#rIv=|Vyz08mBws%yKfbT*>mUB{r{h;G>wsVU6kIJ}_wDemJg0IOETGvZx4eiU;YIVx}sAJ1X?piiDH@lBZ zt=?#7THy2Ra=Oxrw30k=7dI9ad7dxZ3+F5md|~Fu@7Wxjxtm%Z&C{S}(7eXFtx%B$ z#7K@BC9L94HCdH>oFbDh3dNL~s?ojZDxN~Aq9yxo9|yjkWkqA!??3BH7w6QNqNHvY z{i=mNRbiO=dd0Qms#sfT`Wolr;|5n{b0*qq2v!v>FdE@N(V&s@$$#1tx5@Y*W2p{1;9S}9{; z7DY_PEQkaPy6{0q1VT3c%~mwNj}P@o@Z)L~&fy zLuJ*lJMfwotXi;Y)Y9R#LzLCM)>g%;rlluee#7LC_%sz7xZm1pw1U=Sr%hTsIsUYT zqrkf75BrGG%c#4S7HKtGL2J))^d0>UqN-JuYR;BJR?S*Z90&8QrzfuhWmWY8%1DKi zQwbtK)9u%vDiy1`*4`7#ah!R<{{H^lQS1}%3Dgzd<9~0Dy4~43iUy7&3ZpWGls#w7 oyorGVJHs|D@c6-hVs9Hi0jwjC9Y-T(jq07*qoM6N<$f`R*tRsaA1 literal 0 HcmV?d00001 diff --git a/textures/result/default_dan.png b/textures/result/default_dan.png new file mode 100644 index 0000000000000000000000000000000000000000..33413c121429b09c3420cee7dbcc5562b295b9a2 GIT binary patch literal 4895 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