mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2024-11-25 05:25:14 +00:00
Arbitrary shirt, pants, glove colors + settings menu (#145)
* Support for more granular player colors You can now configure RGB values for shirt, pants, gloves, and shoes. Due to some limitations, configuring shoes does nothing at the moment. * Remove paletteIndex and friends Restructured and filled in some remaining code to account for that. * Add Edit Palette panel to Player panel * Change PlayerPalette contents to an enum-indexed array, remove shoes This gets rid of all the hokey code doing switch cases on the different parts. * Fix goof with player model selection box Should actually have affect now even if a custom palette is being used. * Fix gap in player color display list commands The extra space was leftover from when I was trying to get shoes working. Forgot to clean it up. * Standardize PlayerParts enum, including for lua constants autogen * djui_panel_player.c: Properly hook sending palette changes on unpause Editing the palette and then unpausing should send out the packet to everyone with the new palette changes (and update the palette preset selection box), but since we weren't hooking that situation before, it would stay changed only for you. You would have had to press the Back button for it to work right. * Allow Lua mods to continue using `paletteIndex`, `overridePaletteIndex` This lets mod code like this still work unchanged: if s.team == 2 then np.overridePaletteIndex = 7 elseif s.team == 1 then np.overridePaletteIndex = 15 else np.overridePaletteIndex = np.paletteIndex end It's essentially faked, and would work strangely if the value of either variable was inspected more closely directly. This should at least handle the typical use case, though. Every frame, `overridePaletteIndex` is checked to see if it was modified from its previous value. If so, `overridePalette` is set to the preset corresponding to the index. `paletteIndex` contains a special value that when used to assign to `overridePaletteIndex`, it copies `palette` into `overridePalette` to restore the real colors, which of course may not follow the presets at all. * characters.h: Pack `PlayerPalette` to eliminate size differences between computers * mario_misc.c: Remove remaining "TODO GAG"
This commit is contained in:
parent
da5cf8230b
commit
dc3ca7c76d
37 changed files with 544 additions and 231 deletions
|
@ -473,8 +473,8 @@ const Gfx luigi_left_hand_closed_shared_dl[] = {
|
|||
};
|
||||
|
||||
const Gfx luigi_left_hand_closed[] = {
|
||||
gsSPLight(&luigi_white_lights_group.l, 1),
|
||||
gsSPLight(&luigi_white_lights_group.a, 2),
|
||||
gsSPCopyLightEXT(1, 7), // glove light, set in mario_misc.c
|
||||
gsSPCopyLightEXT(2, 8),
|
||||
gsSPDisplayList(luigi_left_hand_closed_shared_dl),
|
||||
gsSPEndDisplayList(),
|
||||
};
|
||||
|
@ -711,8 +711,8 @@ const Gfx luigi_right_hand_closed_dl[] = {
|
|||
};
|
||||
|
||||
const Gfx luigi_right_hand_closed[] = {
|
||||
gsSPLight(&luigi_white_lights_group.l, 1),
|
||||
gsSPLight(&luigi_white_lights_group.a, 2),
|
||||
gsSPCopyLightEXT(1, 7), // glove light, set in mario_misc.c
|
||||
gsSPCopyLightEXT(2, 8),
|
||||
gsSPDisplayList(luigi_right_hand_closed_dl),
|
||||
gsSPEndDisplayList(),
|
||||
};
|
||||
|
@ -3049,8 +3049,8 @@ const Gfx luigi_left_hand_open_shared_dl[] = {
|
|||
};
|
||||
|
||||
const Gfx luigi_left_hand_open[] = {
|
||||
gsSPLight(&luigi_white_lights_group.l, 1),
|
||||
gsSPLight(&luigi_white_lights_group.a, 2),
|
||||
gsSPCopyLightEXT(1, 7), // glove light, set in mario_misc.c
|
||||
gsSPCopyLightEXT(2, 8),
|
||||
gsSPDisplayList(luigi_left_hand_open_shared_dl),
|
||||
gsSPEndDisplayList(),
|
||||
};
|
||||
|
@ -3191,8 +3191,8 @@ const Gfx luigi_right_hand_open_dl[] = {
|
|||
};
|
||||
|
||||
const Gfx luigi_right_hand_open[] = {
|
||||
gsSPLight(&luigi_white_lights_group.l, 1),
|
||||
gsSPLight(&luigi_white_lights_group.a, 2),
|
||||
gsSPCopyLightEXT(1, 7), // glove light, set in mario_misc.c
|
||||
gsSPCopyLightEXT(2, 8),
|
||||
gsSPDisplayList(luigi_right_hand_open_dl),
|
||||
gsSPEndDisplayList(),
|
||||
};
|
||||
|
@ -3446,8 +3446,8 @@ const Gfx luigi_right_hand_cap_bottom_dl[] = {
|
|||
|
||||
const Gfx luigi_right_hand_cap_dl[] = {
|
||||
gsSPDisplayList(luigi_right_hand_cap_top_dl),
|
||||
gsSPLight(&luigi_white_lights_group.l, 1),
|
||||
gsSPLight(&luigi_white_lights_group.a, 2),
|
||||
gsSPCopyLightEXT(1, 7), // glove light, set in mario_misc.c
|
||||
gsSPCopyLightEXT(2, 8),
|
||||
gsSPDisplayList(luigi_right_hand_cap_hand_position_dl),
|
||||
gsSPLight(&luigi_brown2_lights_group.l, 1),
|
||||
gsSPLight(&luigi_brown2_lights_group.a, 2),
|
||||
|
@ -3751,8 +3751,8 @@ const Gfx luigi_right_hand_peace_shared_dl[] = {
|
|||
};
|
||||
|
||||
const Gfx luigi_right_hand_peace[] = {
|
||||
gsSPLight(&luigi_white_lights_group.l, 1),
|
||||
gsSPLight(&luigi_white_lights_group.a, 2),
|
||||
gsSPCopyLightEXT(1, 7), // glove light, set in mario_misc.c
|
||||
gsSPCopyLightEXT(2, 8),
|
||||
gsSPDisplayList(luigi_right_hand_peace_shared_dl),
|
||||
gsSPEndDisplayList(),
|
||||
};
|
||||
|
|
|
@ -651,8 +651,8 @@ const Gfx mario_left_hand_closed_shared_dl[] = {
|
|||
|
||||
// 0x0400D8F0 - 0x0400D910
|
||||
const Gfx mario_left_hand_closed[] = {
|
||||
gsSPLight(&mario_white_lights_group.l, 1),
|
||||
gsSPLight(&mario_white_lights_group.a, 2),
|
||||
gsSPCopyLightEXT(1, 7), // glove light, set in mario_misc.c
|
||||
gsSPCopyLightEXT(2, 8),
|
||||
gsSPDisplayList(mario_left_hand_closed_shared_dl),
|
||||
gsSPEndDisplayList(),
|
||||
};
|
||||
|
@ -897,8 +897,8 @@ const Gfx mario_right_hand_closed_dl[] = {
|
|||
|
||||
// 0x0400E458 - 0x0400E478
|
||||
const Gfx mario_right_hand_closed[] = {
|
||||
gsSPLight(&mario_white_lights_group.l, 1),
|
||||
gsSPLight(&mario_white_lights_group.a, 2),
|
||||
gsSPCopyLightEXT(1, 7), // glove light, set in mario_misc.c
|
||||
gsSPCopyLightEXT(2, 8),
|
||||
gsSPDisplayList(mario_right_hand_closed_dl),
|
||||
gsSPEndDisplayList(),
|
||||
};
|
||||
|
@ -3444,8 +3444,8 @@ const Gfx mario_medium_poly_left_hand_closed_shared_dl[] = {
|
|||
|
||||
// 0x04014DC0 - 0x04014DE0
|
||||
const Gfx mario_medium_poly_left_hand_closed[] = {
|
||||
gsSPLight(&mario_white_lights_group.l, 1),
|
||||
gsSPLight(&mario_white_lights_group.a, 2),
|
||||
gsSPLight(&mario_white_lights_group.l, 7),
|
||||
gsSPLight(&mario_white_lights_group.a, 8),
|
||||
gsSPDisplayList(mario_medium_poly_left_hand_closed_shared_dl),
|
||||
gsSPEndDisplayList(),
|
||||
};
|
||||
|
@ -3483,8 +3483,8 @@ const Gfx mario_medium_poly_right_arm_shared_dl[] = {
|
|||
|
||||
// 0x04014F40 - 0x04014F60
|
||||
const Gfx mario_medium_poly_right_arm[] = {
|
||||
gsSPCopyLightEXT(1, 5), // gsSPLight(&mario_red_lights_group.l, 1),
|
||||
gsSPCopyLightEXT(2, 6), // gsSPLight(&mario_red_lights_group.a, 2),
|
||||
gsSPCopyLightEXT(1, 7), // gsSPLight(&mario_red_lights_group.l, 1),
|
||||
gsSPCopyLightEXT(2, 8), // gsSPLight(&mario_red_lights_group.a, 2),
|
||||
gsSPDisplayList(mario_medium_poly_right_arm_shared_dl),
|
||||
gsSPEndDisplayList(),
|
||||
};
|
||||
|
@ -3606,8 +3606,8 @@ const Gfx mario_medium_poly_right_hand_closed_dl[] = {
|
|||
|
||||
// 0x040154E0 - 0x04015500
|
||||
const Gfx mario_medium_poly_right_hand_closed[] = {
|
||||
gsSPLight(&mario_white_lights_group.l, 1),
|
||||
gsSPLight(&mario_white_lights_group.a, 2),
|
||||
gsSPCopyLightEXT(1, 7), // glove light, set in mario_misc.c
|
||||
gsSPCopyLightEXT(2, 8),
|
||||
gsSPDisplayList(mario_medium_poly_right_hand_closed_dl),
|
||||
gsSPEndDisplayList(),
|
||||
};
|
||||
|
@ -4253,8 +4253,8 @@ const Gfx mario_low_poly_left_hand_closed_shared_dl[] = {
|
|||
|
||||
// 0x04016E80 - 0x04016EA0
|
||||
const Gfx mario_low_poly_left_hand_closed[] = {
|
||||
gsSPLight(&mario_white_lights_group.l, 1),
|
||||
gsSPLight(&mario_white_lights_group.a, 2),
|
||||
gsSPCopyLightEXT(1, 7), // glove light, set in mario_misc.c
|
||||
gsSPCopyLightEXT(2, 8),
|
||||
gsSPDisplayList(mario_low_poly_left_hand_closed_shared_dl),
|
||||
gsSPEndDisplayList(),
|
||||
};
|
||||
|
@ -4344,8 +4344,8 @@ const Gfx mario_low_poly_right_hand_closed_dl[] = {
|
|||
|
||||
// 0x040171C0 - 0x040171E0
|
||||
const Gfx mario_low_poly_right_hand_closed[] = {
|
||||
gsSPLight(&mario_white_lights_group.l, 1),
|
||||
gsSPLight(&mario_white_lights_group.a, 2),
|
||||
gsSPCopyLightEXT(1, 7), // glove light, set in mario_misc.c
|
||||
gsSPCopyLightEXT(2, 8),
|
||||
gsSPDisplayList(mario_low_poly_right_hand_closed_dl),
|
||||
gsSPEndDisplayList(),
|
||||
};
|
||||
|
@ -5599,8 +5599,8 @@ const Gfx mario_left_hand_open_shared_dl[] = {
|
|||
|
||||
// 0x04019CA0 - 0x04019CC0
|
||||
const Gfx mario_left_hand_open[] = {
|
||||
gsSPLight(&mario_white_lights_group.l, 1),
|
||||
gsSPLight(&mario_white_lights_group.a, 2),
|
||||
gsSPCopyLightEXT(1, 7), // glove light, set in mario_misc.c
|
||||
gsSPCopyLightEXT(2, 8),
|
||||
gsSPDisplayList(mario_left_hand_open_shared_dl),
|
||||
gsSPEndDisplayList(),
|
||||
};
|
||||
|
@ -5758,8 +5758,8 @@ const Gfx mario_right_hand_open_dl[] = {
|
|||
|
||||
// 0x0401A428 - 0x0401A448
|
||||
const Gfx mario_right_hand_open[] = {
|
||||
gsSPLight(&mario_white_lights_group.l, 1),
|
||||
gsSPLight(&mario_white_lights_group.a, 2),
|
||||
gsSPCopyLightEXT(1, 7), // glove light, set in mario_misc.c
|
||||
gsSPCopyLightEXT(2, 8),
|
||||
gsSPDisplayList(mario_right_hand_open_dl),
|
||||
gsSPEndDisplayList(),
|
||||
};
|
||||
|
@ -6008,8 +6008,8 @@ const Gfx mario_right_hand_cap_bottom_dl[] = {
|
|||
// 0x0401AF20 - 0x0401AF60
|
||||
const Gfx mario_right_hand_cap_dl[] = {
|
||||
gsSPDisplayList(mario_right_hand_cap_top_dl),
|
||||
gsSPLight(&mario_white_lights_group.l, 1),
|
||||
gsSPLight(&mario_white_lights_group.a, 2),
|
||||
gsSPCopyLightEXT(1, 7), // glove light, set in mario_misc.c
|
||||
gsSPCopyLightEXT(2, 8),
|
||||
gsSPDisplayList(mario_right_hand_cap_hand_position_dl),
|
||||
gsSPLight(&mario_brown2_lights_group.l, 1),
|
||||
gsSPLight(&mario_brown2_lights_group.a, 2),
|
||||
|
@ -6401,8 +6401,8 @@ const Gfx mario_right_hand_peace_shared_dl[] = {
|
|||
|
||||
// 0x0401BF30 - 0x0401BF50
|
||||
const Gfx mario_right_hand_peace[] = {
|
||||
gsSPLight(&mario_white_lights_group.l, 1),
|
||||
gsSPLight(&mario_white_lights_group.a, 2),
|
||||
gsSPCopyLightEXT(1, 7), // glove light, set in mario_misc.c
|
||||
gsSPCopyLightEXT(2, 8),
|
||||
gsSPDisplayList(mario_right_hand_peace_shared_dl),
|
||||
gsSPEndDisplayList(),
|
||||
};
|
||||
|
|
|
@ -807,8 +807,8 @@ const Gfx toad_player_dl_cap[] = {
|
|||
gsDPPipeSync(),
|
||||
gsDPSetCombineMode(G_CC_SHADEFADEA, G_CC_SHADEFADEA),
|
||||
|
||||
gsSPLight(&toad_player_lights_cap.l, 1),
|
||||
gsSPLight(&toad_player_lights_cap.a, 2),
|
||||
gsSPCopyLightEXT(1, 7), // glove light, set in mario_misc.c
|
||||
gsSPCopyLightEXT(2, 8),
|
||||
|
||||
gsSPDisplayList(toad_player_dl_cap_inner),
|
||||
|
||||
|
|
|
@ -3687,7 +3687,8 @@ Gfx mat_waluigi_gloves_v3[] = {
|
|||
gsDPPipeSync(),
|
||||
gsDPSetTile(G_IM_FMT_RGBA, G_IM_SIZ_16b, 8, 0, 0, 0, G_TX_WRAP | G_TX_NOMIRROR, 5, 0, G_TX_WRAP | G_TX_NOMIRROR, 5, 0),
|
||||
gsDPSetTileSize(0, 0, 0, 124, 124),
|
||||
gsSPSetLights1(waluigi_gloves_v3_lights),
|
||||
gsSPCopyLightEXT(1, 7), // glove light, set in mario_misc.c
|
||||
gsSPCopyLightEXT(2, 8),
|
||||
gsSPEndDisplayList(),
|
||||
};
|
||||
|
||||
|
|
|
@ -3670,7 +3670,8 @@ Gfx mat_wario_gloves[] = {
|
|||
gsDPPipeSync(),
|
||||
gsDPSetCombineLERP(0, 0, 0, SHADE, 0, 0, 0, ENVIRONMENT, 0, 0, 0, SHADE, 0, 0, 0, ENVIRONMENT),
|
||||
gsSPTexture(65535, 65535, 0, 0, 1),
|
||||
gsSPSetLights1(wario_white_lights_group),
|
||||
gsSPCopyLightEXT(1, 7), // glove light, set in mario_misc.c
|
||||
gsSPCopyLightEXT(2, 8),
|
||||
gsSPEndDisplayList(),
|
||||
};
|
||||
|
||||
|
|
|
@ -64,7 +64,11 @@ override_field_types = {
|
|||
}
|
||||
|
||||
override_field_mutable = {
|
||||
"NetworkPlayer": [ "overrideModelIndex", "overridePaletteIndex" ],
|
||||
"NetworkPlayer": [
|
||||
"overrideModelIndex",
|
||||
"overridePalette",
|
||||
"overridePaletteIndex",
|
||||
],
|
||||
}
|
||||
|
||||
override_field_invisible = {
|
||||
|
|
|
@ -2523,7 +2523,7 @@ SHAKE_SHOCK = 10
|
|||
SHAKE_SMALL_DAMAGE = 3
|
||||
|
||||
--- @type integer
|
||||
PALETTE_MAX = 32
|
||||
PALETTE_PRESET_MAX = 32
|
||||
|
||||
--- @class CharacterSound
|
||||
|
||||
|
@ -2682,6 +2682,20 @@ CT_WARIO = 4
|
|||
--- @type CharacterType
|
||||
CT_MAX = 5
|
||||
|
||||
--- @class PlayerParts
|
||||
|
||||
--- @type PlayerParts
|
||||
SHIRT = 0
|
||||
|
||||
--- @type PlayerParts
|
||||
PANTS = 1
|
||||
|
||||
--- @type PlayerParts
|
||||
GLOVES = 2
|
||||
|
||||
--- @type PlayerParts
|
||||
PLAYER_PART_MAX = 3
|
||||
|
||||
--- @class DialogId
|
||||
|
||||
--- @type DialogId
|
||||
|
@ -4460,6 +4474,9 @@ UNKNOWN_LOCAL_INDEX = (-1)
|
|||
--- @type integer
|
||||
UNKNOWN_NETWORK_INDEX = (-1)
|
||||
|
||||
--- @type integer
|
||||
USE_REAL_PALETTE_VAR = 0xFF
|
||||
|
||||
--- @class NetworkPlayerType
|
||||
|
||||
--- @type NetworkPlayerType
|
||||
|
|
|
@ -37,6 +37,12 @@ gLevelValues = {}
|
|||
--- @type BehaviorValues
|
||||
gBehaviorValues = {}
|
||||
|
||||
--- @type BehaviorValues
|
||||
gBehaviorValues = {}
|
||||
|
||||
--- @type PlayerPalette[]
|
||||
gPalettePresets = {}
|
||||
|
||||
-----------
|
||||
-- hooks --
|
||||
-----------
|
||||
|
|
|
@ -786,7 +786,10 @@
|
|||
--- @field public name string
|
||||
--- @field public onRxSeqId integer
|
||||
--- @field public overrideModelIndex integer
|
||||
--- @field public overridePalette PlayerPalette
|
||||
--- @field public overridePaletteIndex integer
|
||||
--- @field public overridePaletteIndexLp integer
|
||||
--- @field public palette PlayerPalette
|
||||
--- @field public paletteIndex integer
|
||||
--- @field public type integer
|
||||
|
||||
|
@ -1602,6 +1605,8 @@
|
|||
--- @field public prevFloorType integer
|
||||
--- @field public waterHeight number
|
||||
|
||||
--- @class PlayerPalette
|
||||
|
||||
--- @class RayIntersectionInfo
|
||||
--- @field public hitPos Vec3f
|
||||
--- @field public surface Surface
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
- [characters.h](#charactersh)
|
||||
- [enum CharacterSound](#enum-CharacterSound)
|
||||
- [enum CharacterType](#enum-CharacterType)
|
||||
- [enum PlayerParts](#enum-PlayerParts)
|
||||
- [dialog_ids.h](#dialog_idsh)
|
||||
- [enum DialogId](#enum-DialogId)
|
||||
- [djui_hud_utils.h](#djui_hud_utilsh)
|
||||
|
@ -809,7 +810,7 @@
|
|||
<br />
|
||||
|
||||
## [characters.h](#characters.h)
|
||||
- PALETTE_MAX
|
||||
- PALETTE_PRESET_MAX
|
||||
|
||||
### [enum CharacterSound](#CharacterSound)
|
||||
| Identifier | Value |
|
||||
|
@ -870,6 +871,14 @@
|
|||
| CT_WARIO | 4 |
|
||||
| CT_MAX | 5 |
|
||||
|
||||
### [enum PlayerParts](#PlayerParts)
|
||||
| Identifier | Value |
|
||||
| :--------- | :---- |
|
||||
| SHIRT | 0 |
|
||||
| PANTS | 1 |
|
||||
| GLOVES | 2 |
|
||||
| PLAYER_PART_MAX | 3 |
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
@ -1565,6 +1574,7 @@
|
|||
- UNKNOWN_GLOBAL_INDEX
|
||||
- UNKNOWN_LOCAL_INDEX
|
||||
- UNKNOWN_NETWORK_INDEX
|
||||
- USE_REAL_PALETTE_VAR
|
||||
|
||||
### [enum NetworkPlayerType](#NetworkPlayerType)
|
||||
| Identifier | Value |
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
- [ParallelTrackingPoint](#ParallelTrackingPoint)
|
||||
- [PlayerCameraState](#PlayerCameraState)
|
||||
- [PlayerGeometry](#PlayerGeometry)
|
||||
- [PlayerPalette](#PlayerPalette)
|
||||
- [RayIntersectionInfo](#RayIntersectionInfo)
|
||||
- [SPTask](#SPTask)
|
||||
- [ServerSettings](#ServerSettings)
|
||||
|
@ -1123,7 +1124,10 @@
|
|||
| name | `string` | read-only |
|
||||
| onRxSeqId | `integer` | read-only |
|
||||
| overrideModelIndex | `integer` | |
|
||||
| overridePalette | [PlayerPalette](structs.md#PlayerPalette) | |
|
||||
| overridePaletteIndex | `integer` | |
|
||||
| overridePaletteIndexLp | `integer` | read-only |
|
||||
| palette | [PlayerPalette](structs.md#PlayerPalette) | read-only |
|
||||
| paletteIndex | `integer` | read-only |
|
||||
| type | `integer` | read-only |
|
||||
|
||||
|
@ -2007,6 +2011,15 @@
|
|||
|
||||
<br />
|
||||
|
||||
## [PlayerPalette](#PlayerPalette)
|
||||
|
||||
| Field | Type | Access |
|
||||
| ----- | ---- | ------ |
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [RayIntersectionInfo](#RayIntersectionInfo)
|
||||
|
||||
| Field | Type | Access |
|
||||
|
|
|
@ -372,11 +372,11 @@ function mario_update(m)
|
|||
|
||||
-- update palette
|
||||
if s.team == 2 then
|
||||
np.overridePaletteIndex = 7
|
||||
np.overridePalette = gPalettePresets[7]
|
||||
elseif s.team == 1 then
|
||||
np.overridePaletteIndex = 15
|
||||
np.overridePalette = gPalettePresets[15]
|
||||
else
|
||||
np.overridePaletteIndex = np.paletteIndex
|
||||
np.overridePalette = np.palette
|
||||
end
|
||||
|
||||
-- set metal
|
||||
|
|
|
@ -1262,13 +1262,13 @@ function mario_update(m)
|
|||
local s = gPlayerSyncTable[m.playerIndex]
|
||||
local np = gNetworkPlayers[m.playerIndex]
|
||||
if s.team == 2 then
|
||||
np.overridePaletteIndex = 7
|
||||
np.overridePalette = gPalettePresets[7]
|
||||
m.marioBodyState.modelState = 0
|
||||
elseif s.team == 1 then
|
||||
np.overridePaletteIndex = 15
|
||||
np.overridePalette = gPalettePresets[15]
|
||||
m.marioBodyState.modelState = 0
|
||||
else
|
||||
np.overridePaletteIndex = np.paletteIndex
|
||||
np.overridePalette = np.palette
|
||||
m.marioBodyState.modelState = MODEL_STATE_NOISE_ALPHA
|
||||
end
|
||||
m.health = 0x880
|
||||
|
|
|
@ -355,6 +355,55 @@ struct Character gCharacters[CT_MAX] = {
|
|||
},
|
||||
};
|
||||
|
||||
const struct PlayerPalette DEFAULT_MARIO_PALETTE = {{{0xff, 0x00, 0x00}, {0x00, 0x00, 0xff}, {0xff, 0xff, 0xff}}};
|
||||
|
||||
const struct PlayerPalette gPalettePresets[PALETTE_PRESET_MAX] = {
|
||||
//shirt //pants //gloves
|
||||
|
||||
// default mario
|
||||
{{{0xff, 0x00, 0x00}, {0x00, 0x00, 0xff}, {0xff, 0xff, 0xff}}},
|
||||
// default luigi
|
||||
{{{0x00, 0x98, 0x00}, {0x00, 0x00, 0xfe}, {0xff, 0xff, 0xff}}},
|
||||
// fake waluigi
|
||||
{{{0x6d, 0x3c, 0x9a}, {0x2c, 0x26, 0x3f}, {0xff, 0xff, 0xff}}},
|
||||
// fake wario
|
||||
{{{0xf9, 0xeb, 0x30}, {0x7f, 0x20, 0x7a}, {0xff, 0xff, 0xff}}},
|
||||
|
||||
{{{0x7b, 0x00, 0xde}, {0xff, 0x00, 0x00}, {0xff, 0xff, 0xff}}},
|
||||
{{{0x95, 0x43, 0x01}, {0xc6, 0xb1, 0x32}, {0xff, 0xff, 0xff}}},
|
||||
{{{0x4c, 0x5f, 0x20}, {0x07, 0x09, 0x07}, {0xff, 0xff, 0xff}}},
|
||||
{{{0x00, 0x2f, 0xc8}, {0xbf, 0xde, 0xff}, {0xff, 0xff, 0xff}}},
|
||||
{{{0x11, 0x11, 0x11}, {0xf8, 0x3b, 0x05}, {0xff, 0xff, 0xff}}},
|
||||
{{{0xc1, 0x2c, 0x72}, {0x34, 0x16, 0x0d}, {0xff, 0xff, 0xff}}},
|
||||
{{{0xff, 0x96, 0xc8}, {0xff, 0x00, 0x00}, {0xff, 0xff, 0xff}}},
|
||||
{{{0x4c, 0xff, 0x4c}, {0x81, 0x00, 0x00}, {0xff, 0xff, 0xff}}},
|
||||
{{{0xa9, 0x78, 0xfc}, {0x61, 0x3d, 0x2e}, {0xff, 0xff, 0xff}}},
|
||||
|
||||
{{{0x84, 0x60, 0x00}, {0x00, 0x46, 0x5c}, {0xff, 0xff, 0xff}}},
|
||||
{{{0x5a, 0x94, 0xff}, {0x4f, 0x31, 0x8b}, {0xff, 0xff, 0xff}}},
|
||||
{{{0x68, 0x0a, 0x17}, {0x23, 0x11, 0x03}, {0xff, 0xff, 0xff}}},
|
||||
{{{0x95, 0xd0, 0x8f}, {0x53, 0x39, 0x3d}, {0xff, 0xff, 0xff}}},
|
||||
|
||||
{{{0x37, 0x32, 0x42}, {0xe6, 0xe3, 0xff}, {0xff, 0xff, 0xff}}},
|
||||
{{{0xff, 0x8a, 0x00}, {0x00, 0x51, 0x10}, {0xff, 0xff, 0xff}}},
|
||||
{{{0x65, 0xfa, 0xff}, {0x4c, 0x1e, 0x3f}, {0xff, 0xff, 0xff}}},
|
||||
|
||||
{{{0xe6, 0xe6, 0xe6}, {0xb2, 0x28, 0x18}, {0xff, 0xff, 0xff}}},
|
||||
{{{0xe6, 0xe6, 0xe6}, {0x00, 0x98, 0x00}, {0xff, 0xff, 0xff}}},
|
||||
{{{0xe6, 0xe6, 0xe6}, {0x6d, 0x3c, 0x9a}, {0xff, 0xff, 0xff}}},
|
||||
{{{0xe6, 0xe6, 0xe6}, {0xf9, 0xeb, 0x30}, {0xff, 0xff, 0xff}}},
|
||||
|
||||
{{{0xe7, 0xe7, 0x21}, {0x17, 0x18, 0x15}, {0xff, 0xff, 0xff}}},
|
||||
{{{0xaa, 0x27, 0x31}, {0xf7, 0x9a, 0x47}, {0xff, 0xff, 0xff}}},
|
||||
{{{0x55, 0x92, 0xb2}, {0xf7, 0xc2, 0x45}, {0xff, 0xff, 0xff}}},
|
||||
{{{0x10, 0x1b, 0x2e}, {0xeb, 0x8a, 0x4b}, {0xff, 0xff, 0xff}}},
|
||||
{{{0x3b, 0x8f, 0xf7}, {0xd6, 0x35, 0x4d}, {0xff, 0xff, 0xff}}},
|
||||
{{{0xff, 0x8e, 0xb2}, {0xd6, 0x35, 0x4d}, {0xff, 0xff, 0xff}}},
|
||||
|
||||
{{{0x47, 0xc5, 0xff}, {0xb2, 0x28, 0x18}, {0xff, 0xff, 0xff}}},
|
||||
{{{0x47, 0xc5, 0xff}, {0x00, 0x98, 0x00}, {0xff, 0xff, 0xff}}},
|
||||
};
|
||||
|
||||
enum AnimType {
|
||||
ANIM_TYPE_NONE,
|
||||
ANIM_TYPE_LOWY,
|
||||
|
|
|
@ -2,9 +2,25 @@
|
|||
#define CHARACTERS_H
|
||||
#include "PR/ultratypes.h"
|
||||
#include "types.h"
|
||||
#include "pc/configfile.h"
|
||||
// NOTE: do not include any additional headers
|
||||
|
||||
#define PALETTE_MAX 32
|
||||
#define PALETTE_PRESET_MAX 32
|
||||
|
||||
enum PlayerParts {
|
||||
SHIRT, PANTS, GLOVES, PLAYER_PART_MAX
|
||||
//SHOES (can't implement due to light limit)
|
||||
};
|
||||
|
||||
#pragma pack(1)
|
||||
struct PlayerPalette {
|
||||
//rgb
|
||||
u8 parts[PLAYER_PART_MAX][3];
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
extern const struct PlayerPalette DEFAULT_MARIO_PALETTE;
|
||||
extern const struct PlayerPalette gPalettePresets[PALETTE_PRESET_MAX];
|
||||
|
||||
enum CharacterType {
|
||||
CT_MARIO,
|
||||
|
|
|
@ -54,8 +54,7 @@ enum UnlockDoorStarStates {
|
|||
};
|
||||
|
||||
struct PlayerColor {
|
||||
Lights1 shirt;
|
||||
Lights1 pants;
|
||||
Lights1 parts[PLAYER_PART_MAX];
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -80,58 +79,14 @@ struct MarioBodyState gBodyStates[MAX_PLAYERS];
|
|||
struct GraphNodeObject gMirrorMario[MAX_PLAYERS]; // copy of Mario's geo node for drawing mirror Mario
|
||||
|
||||
// ambient color is always half the diffuse color, so we can pull a macro
|
||||
#define DEFINE_PLAYER_COLOR(sr, sg, sb, pr, pg, pb) \
|
||||
{ \
|
||||
gdSPDefLights1((sr >> 1), (sg >> 1), (sb >> 1), sr, sg, sb, 0x28, 0x28, 0x28), \
|
||||
gdSPDefLights1((pr >> 1), (pg >> 1), (pb >> 1), pr, pg, pb, 0x28, 0x28, 0x28), \
|
||||
}
|
||||
#define PALETTE_TO_LIGHTS(palette) \
|
||||
{{ \
|
||||
gdSPDefLights1((palette.parts[SHIRT][0] >> 1), (palette.parts[SHIRT][1] >> 1), (palette.parts[SHIRT][2] >> 1), palette.parts[SHIRT][0], palette.parts[SHIRT][1], palette.parts[SHIRT][2], 0x28, 0x28, 0x28), \
|
||||
gdSPDefLights1((palette.parts[PANTS][0] >> 1), (palette.parts[PANTS][1] >> 1), (palette.parts[PANTS][2] >> 1), palette.parts[PANTS][0], palette.parts[PANTS][1], palette.parts[PANTS][2], 0x28, 0x28, 0x28), \
|
||||
gdSPDefLights1((palette.parts[GLOVES][0] >> 1), (palette.parts[GLOVES][1] >> 1), (palette.parts[GLOVES][2] >> 1), palette.parts[GLOVES][0], palette.parts[GLOVES][1], palette.parts[GLOVES][2], 0x28, 0x28, 0x28), \
|
||||
}}
|
||||
|
||||
struct PlayerColor gPlayerColors[PALETTE_MAX] = {
|
||||
// default mario
|
||||
DEFINE_PLAYER_COLOR(0xff, 0x00, 0x00, /**/ 0x00, 0x00, 0xff),
|
||||
// default luigi
|
||||
DEFINE_PLAYER_COLOR(0x00, 0x98, 0x00, /**/ 0x00, 0x00, 0xfe),
|
||||
// fake waluigi
|
||||
DEFINE_PLAYER_COLOR(0x6d, 0x3c, 0x9a, /**/ 0x2c, 0x26, 0x3f),
|
||||
// fake wario
|
||||
DEFINE_PLAYER_COLOR(0xf9, 0xeb, 0x30, /**/ 0x7f, 0x20, 0x7a),
|
||||
|
||||
DEFINE_PLAYER_COLOR(0x7b, 0x00, 0xde, /**/ 0xff, 0x00, 0x00),
|
||||
DEFINE_PLAYER_COLOR(0x95, 0x43, 0x01, /**/ 0xc6, 0xb1, 0x32),
|
||||
DEFINE_PLAYER_COLOR(0x4c, 0x5f, 0x20, /**/ 0x07, 0x09, 0x07),
|
||||
DEFINE_PLAYER_COLOR(0x00, 0x2f, 0xc8, /**/ 0xbf, 0xde, 0xff),
|
||||
DEFINE_PLAYER_COLOR(0x11, 0x11, 0x11, /**/ 0xf8, 0x3b, 0x05),
|
||||
DEFINE_PLAYER_COLOR(0xc1, 0x2c, 0x72, /**/ 0x34, 0x16, 0x0d),
|
||||
DEFINE_PLAYER_COLOR(0xff, 0x96, 0xc8, /**/ 0xff, 0x00, 0x00),
|
||||
DEFINE_PLAYER_COLOR(0x4c, 0xff, 0x4c, /**/ 0x81, 0x00, 0x00),
|
||||
DEFINE_PLAYER_COLOR(0xa9, 0x78, 0xfc, /**/ 0x61, 0x3d, 0x2e),
|
||||
|
||||
DEFINE_PLAYER_COLOR(0x84, 0x60, 0x00, /**/ 0x00, 0x46, 0x5c),
|
||||
DEFINE_PLAYER_COLOR(0x5a, 0x94, 0xff, /**/ 0x4f, 0x31, 0x8b),
|
||||
DEFINE_PLAYER_COLOR(0x68, 0x0a, 0x17, /**/ 0x23, 0x11, 0x03),
|
||||
DEFINE_PLAYER_COLOR(0x95, 0xd0, 0x8f, /**/ 0x53, 0x39, 0x3d),
|
||||
|
||||
DEFINE_PLAYER_COLOR(0x37, 0x32, 0x42, /**/ 0xe6, 0xe3, 0xff),
|
||||
DEFINE_PLAYER_COLOR(0xff, 0x8a, 0x00, /**/ 0x00, 0x51, 0x10),
|
||||
DEFINE_PLAYER_COLOR(0x65, 0xfa, 0xff, /**/ 0x4c, 0x1e, 0x3f),
|
||||
|
||||
DEFINE_PLAYER_COLOR(0xe6, 0xe6, 0xe6, /**/ 0xb2, 0x28, 0x18),
|
||||
DEFINE_PLAYER_COLOR(0xe6, 0xe6, 0xe6, /**/ 0x00, 0x98, 0x00),
|
||||
DEFINE_PLAYER_COLOR(0xe6, 0xe6, 0xe6, /**/ 0x6d, 0x3c, 0x9a),
|
||||
DEFINE_PLAYER_COLOR(0xe6, 0xe6, 0xe6, /**/ 0xf9, 0xeb, 0x30),
|
||||
|
||||
DEFINE_PLAYER_COLOR(0xe7, 0xe7, 0x21, /**/ 0x17, 0x18, 0x15),
|
||||
DEFINE_PLAYER_COLOR(0xaa, 0x27, 0x31, /**/ 0xf7, 0x9a, 0x47),
|
||||
DEFINE_PLAYER_COLOR(0x55, 0x92, 0xb2, /**/ 0xf7, 0xc2, 0x45),
|
||||
DEFINE_PLAYER_COLOR(0x10, 0x1b, 0x2e, /**/ 0xeb, 0x8a, 0x4b),
|
||||
DEFINE_PLAYER_COLOR(0x3b, 0x8f, 0xf7, /**/ 0xd6, 0x35, 0x4d),
|
||||
DEFINE_PLAYER_COLOR(0xff, 0x8e, 0xb2, /**/ 0xd6, 0x35, 0x4d),
|
||||
|
||||
DEFINE_PLAYER_COLOR(0x47, 0xc5, 0xff, /**/ 0xb2, 0x28, 0x18),
|
||||
DEFINE_PLAYER_COLOR(0x47, 0xc5, 0xff, /**/ 0x00, 0x98, 0x00),
|
||||
};
|
||||
|
||||
const size_t gNumPlayerColors = sizeof(gPlayerColors) / sizeof(*gPlayerColors);
|
||||
struct PlayerColor gNetworkPlayerColors[MAX_PLAYERS];
|
||||
|
||||
// This whole file is weirdly organized. It has to be the same file due
|
||||
// to rodata boundaries and function aligns, which means the programmer
|
||||
|
@ -139,36 +94,6 @@ const size_t gNumPlayerColors = sizeof(gPlayerColors) / sizeof(*gPlayerColors);
|
|||
// (message NPC related things, the Mario head geo, and Mario geo
|
||||
// functions)
|
||||
|
||||
/**
|
||||
* Set the Light1 struct from player colors.
|
||||
* The 4th component is the shade factor (difference between ambient and diffuse),
|
||||
* usually set to 1.
|
||||
*/
|
||||
void set_player_colors(u8 paletteIndex, const u8 shirt[4], const u8 pants[4]) {
|
||||
// choose the last color in the table for extra players
|
||||
if (paletteIndex >= gNumPlayerColors) paletteIndex = gNumPlayerColors - 1;
|
||||
const u8 pAmb[3] = { pants[0] >> pants[3], pants[1] >> pants[3], pants[2] >> pants[3] };
|
||||
const u8 sAmb[3] = { shirt[0] >> shirt[3], shirt[1] >> shirt[3], shirt[2] >> shirt[3] };
|
||||
gPlayerColors[paletteIndex].pants =
|
||||
(Lights1) gdSPDefLights1(pAmb[0], pAmb[1], pAmb[2], pants[0], pants[1], pants[2], 0x28, 0x28, 0x28);
|
||||
gPlayerColors[paletteIndex].shirt =
|
||||
(Lights1) gdSPDefLights1(sAmb[0], sAmb[1], sAmb[2], shirt[0], shirt[1], shirt[2], 0x28, 0x28, 0x28);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the specified color for player globalIndex.
|
||||
* 0 = shirt, 1 = pants
|
||||
* Returns RGB, not RGBA!
|
||||
*/
|
||||
u8 *get_player_color(u8 paletteIndex, const s32 which) {
|
||||
// choose the last color in the table for extra players
|
||||
if (paletteIndex >= gNumPlayerColors) paletteIndex = gNumPlayerColors - 1;
|
||||
if (which == 0)
|
||||
return gPlayerColors[paletteIndex].shirt.l[0].l.col;
|
||||
else
|
||||
return gPlayerColors[paletteIndex].pants.l[0].l.col;
|
||||
}
|
||||
|
||||
/**
|
||||
* Geo node script that draws Mario's head on the title screen.
|
||||
*/
|
||||
|
@ -827,21 +752,26 @@ Gfx* geo_mario_set_player_colors(s32 callContext, struct GraphNode* node, UNUSED
|
|||
struct GraphNodeGenerated* asGenerated = (struct GraphNodeGenerated*) node;
|
||||
Gfx* gfx = NULL;
|
||||
u8 index = geo_get_processing_object_index();
|
||||
u8 colorIndex = gNetworkPlayers[index].overridePaletteIndex;
|
||||
|
||||
struct PlayerColor color = PALETTE_TO_LIGHTS(gNetworkPlayers[index].overridePalette);
|
||||
|
||||
gNetworkPlayerColors[index] = color;
|
||||
|
||||
struct MarioBodyState* bodyState = &gBodyStates[index];
|
||||
|
||||
if (callContext == GEO_CONTEXT_RENDER) {
|
||||
// extra players get last color
|
||||
if (colorIndex >= gNumPlayerColors) colorIndex = gNumPlayerColors - 1;
|
||||
gfx = alloc_display_list(5 * sizeof(*gfx));
|
||||
gfx = alloc_display_list(7 * sizeof(*gfx));
|
||||
if (gfx == NULL) { return NULL; }
|
||||
// put the player colors into lights 3, 4, 5, 6
|
||||
// put the player colors into lights 3, 4, 5, 6, 7, 8
|
||||
// they will be later copied to lights 1, 2 with gsSPCopyLightEXT
|
||||
gSPLight(gfx + 0, &gPlayerColors[colorIndex].pants.l, 3);
|
||||
gSPLight(gfx + 1, &gPlayerColors[colorIndex].pants.a, 4);
|
||||
gSPLight(gfx + 2, &gPlayerColors[colorIndex].shirt.l, 5);
|
||||
gSPLight(gfx + 3, &gPlayerColors[colorIndex].shirt.a, 6);
|
||||
gSPEndDisplayList(gfx + 4);
|
||||
gSPLight(gfx + 0, &gNetworkPlayerColors[index].parts[PANTS].l, 3);
|
||||
gSPLight(gfx + 1, &gNetworkPlayerColors[index].parts[PANTS].a, 4);
|
||||
gSPLight(gfx + 2, &gNetworkPlayerColors[index].parts[SHIRT].l, 5);
|
||||
gSPLight(gfx + 3, &gNetworkPlayerColors[index].parts[SHIRT].a, 6);
|
||||
gSPLight(gfx + 4, &gNetworkPlayerColors[index].parts[GLOVES].l, 7);
|
||||
gSPLight(gfx + 5, &gNetworkPlayerColors[index].parts[GLOVES].a, 8);
|
||||
gSPEndDisplayList(gfx + 6);
|
||||
u32 layer = LAYER_OPAQUE;
|
||||
if (asGenerated->parameter == 0) {
|
||||
// put on transparent layer if vanish effect, opaque otherwise
|
||||
|
@ -861,24 +791,30 @@ Gfx* geo_mario_set_player_colors(s32 callContext, struct GraphNode* node, UNUSED
|
|||
Gfx* geo_mario_cap_display_list(s32 callContext, struct GraphNode* node, UNUSED Mat4* c) {
|
||||
if (callContext != GEO_CONTEXT_RENDER) { return NULL; }
|
||||
u8 globalIndex = geo_get_processing_object_index();
|
||||
u8 colorIndex = gNetworkPlayers[globalIndex].overridePaletteIndex;
|
||||
|
||||
struct PlayerColor color = PALETTE_TO_LIGHTS(gNetworkPlayers[globalIndex].overridePalette);
|
||||
|
||||
gNetworkPlayerColors[globalIndex] = color;
|
||||
|
||||
u8 charIndex = gNetworkPlayers[globalIndex].overrideModelIndex;
|
||||
if (charIndex >= CT_MAX) { charIndex = 0; }
|
||||
struct Character* character = &gCharacters[charIndex];
|
||||
|
||||
u8 dpLength = 5;
|
||||
u8 dpLength = 7;
|
||||
if (character->capEnemyGfx != NULL) { dpLength++; }
|
||||
if (character->capEnemyDecalGfx != NULL) { dpLength++; }
|
||||
Gfx* gfx = alloc_display_list(dpLength * sizeof(*gfx));
|
||||
if (gfx == NULL) { return NULL; }
|
||||
Gfx* onGfx = gfx;
|
||||
|
||||
// put the player colors into lights 3, 4, 5, 6
|
||||
// put the player colors into lights 3, 4, 5, 6, 7, 8
|
||||
// they will be later copied to lights 1, 2 with gsSPCopyLightEXT
|
||||
gSPLight(onGfx++, &gPlayerColors[colorIndex].pants.l, 3);
|
||||
gSPLight(onGfx++, &gPlayerColors[colorIndex].pants.a, 4);
|
||||
gSPLight(onGfx++, &gPlayerColors[colorIndex].shirt.l, 5);
|
||||
gSPLight(onGfx++, &gPlayerColors[colorIndex].shirt.a, 6);
|
||||
gSPLight(onGfx++, &gNetworkPlayerColors[globalIndex].parts[PANTS].l, 3);
|
||||
gSPLight(onGfx++, &gNetworkPlayerColors[globalIndex].parts[PANTS].a, 4);
|
||||
gSPLight(onGfx++, &gNetworkPlayerColors[globalIndex].parts[SHIRT].l, 5);
|
||||
gSPLight(onGfx++, &gNetworkPlayerColors[globalIndex].parts[SHIRT].a, 6);
|
||||
gSPLight(onGfx++, &gNetworkPlayerColors[globalIndex].parts[GLOVES].l, 7);
|
||||
gSPLight(onGfx++, &gNetworkPlayerColors[globalIndex].parts[GLOVES].a, 8);
|
||||
if (character->capEnemyGfx != NULL) { gSPDisplayList(onGfx++, character->capEnemyGfx); }
|
||||
if (character->capEnemyDecalGfx != NULL) { gSPDisplayList(onGfx++, character->capEnemyDecalGfx); }
|
||||
gSPEndDisplayList(onGfx++);
|
||||
|
|
|
@ -8,10 +8,6 @@
|
|||
|
||||
extern struct GraphNodeObject gMirrorMario[MAX_PLAYERS];
|
||||
extern struct MarioBodyState gBodyStates[MAX_PLAYERS];
|
||||
extern const size_t gNumPlayerColors;
|
||||
|
||||
void set_player_colors(u8 paletteIndex, const u8 shirt[4], const u8 pants[4]);
|
||||
u8 *get_player_color(u8 paletteIndex, const s32 which);
|
||||
|
||||
Gfx *geo_draw_mario_head_goddard(s32 callContext, struct GraphNode *node, Mat4 *c);
|
||||
void bhv_toad_message_loop(void);
|
||||
|
|
|
@ -296,6 +296,25 @@ void bhv_mario_update(void) {
|
|||
particleFlags |= gMarioState->particleFlags;
|
||||
gCurrentObject->oMarioParticleFlags = particleFlags;
|
||||
|
||||
// This code is meant to preserve old Lua mods' ability to set overridePaletteIndex and paletteIndex and still work
|
||||
// as they expected. USE_REAL_PALETTE_VAR is meant to help support cases where mods will do:
|
||||
// np.overridePaletteIndex = np.paletteIndex
|
||||
// to undo the palette override and have it still go back to the new REAL palette stored in `palette`.
|
||||
{
|
||||
struct NetworkPlayer *np = &gNetworkPlayers[gMarioState->playerIndex];
|
||||
|
||||
if (np->overridePaletteIndex != np->overridePaletteIndexLp) {
|
||||
np->overridePaletteIndexLp = np->overridePaletteIndex;
|
||||
|
||||
if (np->overridePaletteIndex == USE_REAL_PALETTE_VAR) {
|
||||
np->overridePalette = np->palette;
|
||||
}
|
||||
else {
|
||||
np->overridePalette = gPalettePresets[np->overridePaletteIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mario code updates MarioState's versions of position etc, so we need
|
||||
// to sync it with the Mario object
|
||||
copy_mario_state_to_object(gMarioState);
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include "pc/crash_handler.h"
|
||||
#include "pc/network/moderator_list.h"
|
||||
|
||||
|
||||
#define ARRAY_LEN(arr) (sizeof(arr) / sizeof(arr[0]))
|
||||
|
||||
enum ConfigOptionType {
|
||||
|
@ -28,6 +27,7 @@ enum ConfigOptionType {
|
|||
CONFIG_TYPE_BIND,
|
||||
CONFIG_TYPE_STRING,
|
||||
CONFIG_TYPE_U64,
|
||||
CONFIG_TYPE_COLOR,
|
||||
};
|
||||
|
||||
struct ConfigOption {
|
||||
|
@ -39,6 +39,7 @@ struct ConfigOption {
|
|||
float* floatValue;
|
||||
char* stringValue;
|
||||
u64* u64Value;
|
||||
u8 (*colorValue)[3];
|
||||
};
|
||||
int maxStringLength;
|
||||
};
|
||||
|
@ -132,7 +133,7 @@ unsigned int configStayInLevelAfterStar = 0;
|
|||
unsigned int configNetworkSystem = 0;
|
||||
char configPlayerName[MAX_PLAYER_STRING] = "";
|
||||
unsigned int configPlayerModel = 0;
|
||||
unsigned int configPlayerPalette = 0;
|
||||
struct PlayerPalette configPlayerPalette = {{{0xff, 0x00, 0x00}, {0x00, 0x00, 0xff}, {0xff, 0xff, 0xff}}};
|
||||
bool configUncappedFramerate = true;
|
||||
unsigned int configFrameLimit = 60;
|
||||
unsigned int configDrawDistance = 5;
|
||||
|
@ -219,7 +220,9 @@ static const struct ConfigOption options[] = {
|
|||
{.name = "coop_player_knockback_strength", .type = CONFIG_TYPE_UINT , .uintValue = &configPlayerKnockbackStrength},
|
||||
{.name = "coop_player_model", .type = CONFIG_TYPE_UINT , .uintValue = &configPlayerModel},
|
||||
{.name = "coop_player_name", .type = CONFIG_TYPE_STRING, .stringValue = (char*)&configPlayerName, .maxStringLength = MAX_PLAYER_STRING},
|
||||
{.name = "coop_player_palette", .type = CONFIG_TYPE_UINT , .uintValue = &configPlayerPalette},
|
||||
{.name = "coop_player_palette_shirt", .type = CONFIG_TYPE_COLOR , .colorValue = &configPlayerPalette.parts[SHIRT]},
|
||||
{.name = "coop_player_palette_pants", .type = CONFIG_TYPE_COLOR , .colorValue = &configPlayerPalette.parts[PANTS]},
|
||||
{.name = "coop_player_palette_gloves", .type = CONFIG_TYPE_COLOR , .colorValue = &configPlayerPalette.parts[GLOVES]},
|
||||
{.name = "coop_stay_in_level_after_star", .type = CONFIG_TYPE_UINT , .uintValue = &configStayInLevelAfterStar},
|
||||
{.name = "share_lives", .type = CONFIG_TYPE_BOOL , .boolValue = &configShareLives},
|
||||
{.name = "disable_popups", .type = CONFIG_TYPE_BOOL , .boolValue = &configDisablePopups},
|
||||
|
@ -405,6 +408,7 @@ const char *configfile_name(void) {
|
|||
void configfile_load(const char *filename) {
|
||||
fs_file_t *file;
|
||||
char *line;
|
||||
unsigned int temp;
|
||||
|
||||
printf("Loading configuration from '%s'\n", filename);
|
||||
|
||||
|
@ -480,6 +484,12 @@ void configfile_load(const char *filename) {
|
|||
case CONFIG_TYPE_U64:
|
||||
sscanf(tokens[1], "%llu", option->u64Value);
|
||||
break;
|
||||
case CONFIG_TYPE_COLOR:
|
||||
for (int i = 0; i < 3 && i < numTokens - 1; ++i) {
|
||||
sscanf(tokens[i + 1], "%x", &temp);
|
||||
(*option->colorValue)[i] = temp;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0); // bad type
|
||||
}
|
||||
|
@ -541,6 +551,9 @@ void configfile_save(const char *filename) {
|
|||
case CONFIG_TYPE_U64:
|
||||
fprintf(file, "%s %llu\n", option->name, *option->u64Value);
|
||||
break;
|
||||
case CONFIG_TYPE_COLOR:
|
||||
fprintf(file, "%s %02x %02x %02x\n", option->name, (*option->colorValue)[0], (*option->colorValue)[1], (*option->colorValue)[2]);
|
||||
break;
|
||||
default:
|
||||
assert(0); // unknown type
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#define CONFIGFILE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "PR/ultratypes.h"
|
||||
#include "game/characters.h"
|
||||
|
||||
#define CONFIGFILE_DEFAULT "sm64config.txt"
|
||||
|
||||
|
@ -88,7 +90,7 @@ extern unsigned int configStayInLevelAfterStar;
|
|||
extern unsigned int configNetworkSystem;
|
||||
extern char configPlayerName[];
|
||||
extern unsigned int configPlayerModel;
|
||||
extern unsigned int configPlayerPalette;
|
||||
extern struct PlayerPalette configPlayerPalette;
|
||||
extern bool configUncappedFramerate;
|
||||
extern unsigned int configFrameLimit;
|
||||
extern unsigned int configDrawDistance;
|
||||
|
|
|
@ -1,10 +1,185 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "djui.h"
|
||||
#include "pc/configfile.h"
|
||||
#include "pc/network/network_player.h"
|
||||
#include "game/level_update.h"
|
||||
#include "game/area.h"
|
||||
|
||||
#define PALETTE_CUSTOM PALETTE_PRESET_MAX
|
||||
|
||||
static unsigned int sPalettePresetIndex = PALETTE_CUSTOM;
|
||||
static unsigned int sCurrentPlayerPart = SHIRT;
|
||||
static unsigned int sSliderChannels[3] = {0};
|
||||
|
||||
static struct DjuiSelectionbox* sPalettePresetSelection;
|
||||
|
||||
static struct DjuiSelectionbox* sPartSelection;
|
||||
static struct DjuiInputbox* sHexColorTextBox;
|
||||
static struct DjuiSlider *sSliderR, *sSliderG, *sSliderB;
|
||||
|
||||
static void djui_panel_player_edit_palette_update_hex_code_box() {
|
||||
char buf[7];
|
||||
static const char digitToChar[] = "0123456789abcdef";
|
||||
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
buf[2*i] = digitToChar[configPlayerPalette.parts[sCurrentPlayerPart][i] >> 4];
|
||||
buf[2*i+1] = digitToChar[configPlayerPalette.parts[sCurrentPlayerPart][i] & 0xF];
|
||||
}
|
||||
|
||||
buf[6] = '\0';
|
||||
|
||||
djui_inputbox_set_text(sHexColorTextBox, buf);
|
||||
}
|
||||
|
||||
static void djui_panel_player_edit_palette_update_palette_display() {
|
||||
if (memcmp(&gNetworkPlayers[0].overridePalette, &gNetworkPlayers[0].palette, sizeof(struct PlayerPalette)) == 0) {
|
||||
gNetworkPlayers[0].overridePalette = configPlayerPalette;
|
||||
}
|
||||
|
||||
gNetworkPlayers[0].palette = configPlayerPalette;
|
||||
}
|
||||
|
||||
static void djui_panel_player_edit_palette_update_sliders() {
|
||||
for (int i = 0; i < 3; i++) sSliderChannels[i] = configPlayerPalette.parts[sCurrentPlayerPart][i];
|
||||
|
||||
djui_slider_update_value(&sSliderR->base);
|
||||
djui_slider_update_value(&sSliderG->base);
|
||||
djui_slider_update_value(&sSliderB->base);
|
||||
}
|
||||
|
||||
static void djui_panel_player_edit_palette_part_changed(UNUSED struct DjuiBase* caller) {
|
||||
djui_panel_player_edit_palette_update_sliders();
|
||||
djui_panel_player_edit_palette_update_hex_code_box();
|
||||
}
|
||||
|
||||
static int char_to_hex_digit(char c) {
|
||||
return (c >= '0' && c <= '9') ? c - '0' : c - 'a' + 10;
|
||||
}
|
||||
|
||||
static void djui_panel_player_edit_palette_hex_code_changed(struct DjuiBase* caller) {
|
||||
struct DjuiInputbox* input = (struct DjuiInputbox*) caller;
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
char c = input->buffer[i];
|
||||
if (c == '\0') return; // all 6 characters must be filled
|
||||
|
||||
if (c >= 'A' && c <= 'Z') {
|
||||
input->buffer[i] = c - 'A' + 'a'; // convert all characters to lowercase
|
||||
}
|
||||
|
||||
if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'))) return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
configPlayerPalette.parts[sCurrentPlayerPart][i] = (char_to_hex_digit(input->buffer[2*i]) << 4) |
|
||||
char_to_hex_digit(input->buffer[2*i] + 1);
|
||||
}
|
||||
|
||||
djui_panel_player_edit_palette_update_sliders();
|
||||
djui_panel_player_edit_palette_update_palette_display();
|
||||
sPalettePresetIndex = PALETTE_CUSTOM;
|
||||
}
|
||||
|
||||
static void djui_panel_player_edit_palette_slider_changed(UNUSED struct DjuiBase* caller, size_t index) {
|
||||
configPlayerPalette.parts[sCurrentPlayerPart][index] = sSliderChannels[index];
|
||||
|
||||
djui_panel_player_edit_palette_update_hex_code_box();
|
||||
djui_panel_player_edit_palette_update_palette_display();
|
||||
sPalettePresetIndex = PALETTE_CUSTOM;
|
||||
}
|
||||
|
||||
static void djui_panel_player_edit_palette_red_changed(UNUSED struct DjuiBase* caller) {
|
||||
djui_panel_player_edit_palette_slider_changed(caller, 0);
|
||||
}
|
||||
|
||||
static void djui_panel_player_edit_palette_green_changed(UNUSED struct DjuiBase* caller) {
|
||||
djui_panel_player_edit_palette_slider_changed(caller, 1);
|
||||
}
|
||||
|
||||
static void djui_panel_player_edit_palette_blue_changed(UNUSED struct DjuiBase* caller) {
|
||||
djui_panel_player_edit_palette_slider_changed(caller, 2);
|
||||
}
|
||||
|
||||
static void (*sSavedDestroy)(struct DjuiBase*);
|
||||
void djui_panel_player_edit_palette_destroy(struct DjuiBase* caller) {
|
||||
if (gNetworkType != NT_NONE) {
|
||||
network_send_player_settings();
|
||||
}
|
||||
|
||||
djui_selectionbox_update_value(&sPalettePresetSelection->base); // since editing palette values can change it
|
||||
|
||||
(*sSavedDestroy)(caller);
|
||||
}
|
||||
|
||||
static void djui_panel_player_edit_palette_create(struct DjuiBase* caller) {
|
||||
char* sPartStrings[PLAYER_PART_MAX] = { "Shirt", "Pants", "Gloves" };
|
||||
|
||||
f32 bodyHeight = 32 * 5 + 64 * 1 + 16 * 5;
|
||||
|
||||
struct DjuiBase* defaultBase = NULL;
|
||||
struct DjuiThreePanel* panel = djui_panel_menu_create(bodyHeight, "\\#ff0800\\P\\#1be700\\A\\#00b3ff\\L\\#ffef00\\E\\#ff0800\\T\\#1be700\\T\\#00b3ff\\E");
|
||||
|
||||
// A bit of a gross hack to send out palette changes and update the palette preset selection box on unpause AND
|
||||
// pressing the Back button
|
||||
sSavedDestroy = panel->base.destroy;
|
||||
panel->base.destroy = djui_panel_player_edit_palette_destroy;
|
||||
|
||||
struct DjuiFlowLayout* body = (struct DjuiFlowLayout*)djui_three_panel_get_body(panel);
|
||||
|
||||
{
|
||||
sCurrentPlayerPart = SHIRT;
|
||||
sPartSelection = djui_selectionbox_create(&body->base, "Part", sPartStrings, PLAYER_PART_MAX, &sCurrentPlayerPart);
|
||||
djui_base_set_size_type(&sPartSelection->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_size(&sPartSelection->base, 1.0f, 32);
|
||||
djui_interactable_hook_value_change(&sPartSelection->base, djui_panel_player_edit_palette_part_changed);
|
||||
|
||||
struct DjuiRect* rect1 = djui_rect_create(&body->base);
|
||||
djui_base_set_size_type(&rect1->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_size(&rect1->base, 1.0f, 32);
|
||||
djui_base_set_color(&rect1->base, 0, 0, 0, 0);
|
||||
{
|
||||
struct DjuiText* text1 = djui_text_create(&rect1->base, "Hex Code");
|
||||
djui_base_set_size_type(&text1->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_color(&text1->base, 200, 200, 200, 255);
|
||||
djui_base_set_size(&text1->base, 0.485f, 64);
|
||||
djui_base_set_alignment(&text1->base, DJUI_HALIGN_LEFT, DJUI_VALIGN_TOP);
|
||||
|
||||
sHexColorTextBox = djui_inputbox_create(&rect1->base, 7);
|
||||
djui_base_set_size_type(&sHexColorTextBox->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_size(&sHexColorTextBox->base, 0.5f, 32);
|
||||
djui_base_set_alignment(&sHexColorTextBox->base, DJUI_HALIGN_RIGHT, DJUI_VALIGN_TOP);
|
||||
djui_panel_player_edit_palette_update_hex_code_box();
|
||||
djui_interactable_hook_value_change(&sHexColorTextBox->base, djui_panel_player_edit_palette_hex_code_changed);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) sSliderChannels[i] = configPlayerPalette.parts[SHIRT][i];
|
||||
|
||||
sSliderR = djui_slider_create(&body->base, "Red", &sSliderChannels[0], 0, 255);
|
||||
djui_base_set_size_type(&sSliderR->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_interactable_hook_value_change(&sSliderR->base, djui_panel_player_edit_palette_red_changed);
|
||||
djui_base_set_size(&sSliderR->base, 1.0f, 32);
|
||||
|
||||
sSliderG = djui_slider_create(&body->base, "Green", &sSliderChannels[1], 0, 255);
|
||||
djui_base_set_size_type(&sSliderG->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_interactable_hook_value_change(&sSliderG->base, djui_panel_player_edit_palette_green_changed);
|
||||
djui_base_set_size(&sSliderG->base, 1.0f, 32);
|
||||
|
||||
sSliderB = djui_slider_create(&body->base, "Blue", &sSliderChannels[2], 0, 255);
|
||||
djui_base_set_size_type(&sSliderB->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_interactable_hook_value_change(&sSliderB->base, djui_panel_player_edit_palette_blue_changed);
|
||||
djui_base_set_size(&sSliderB->base, 1.0f, 32);
|
||||
|
||||
struct DjuiButton* button6 = djui_button_create(&body->base, "Back");
|
||||
djui_base_set_size_type(&button6->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_size(&button6->base, 1.0f, 64);
|
||||
djui_button_set_style(button6, 1);
|
||||
djui_interactable_hook_click(&button6->base, djui_panel_menu_back);
|
||||
}
|
||||
|
||||
djui_panel_add(caller, &panel->base, defaultBase);
|
||||
}
|
||||
|
||||
static bool djui_panel_player_name_valid(char* buffer) {
|
||||
if (buffer[0] == '\0') { return false; }
|
||||
while (*buffer != '\0') {
|
||||
|
@ -39,12 +214,16 @@ static void djui_panel_player_name_on_focus_end(struct DjuiBase* caller) {
|
|||
}
|
||||
}
|
||||
|
||||
void djui_panel_player_value_changed(UNUSED struct DjuiBase* caller) {
|
||||
static void djui_panel_player_value_changed(UNUSED struct DjuiBase* caller) {
|
||||
if (sPalettePresetIndex != PALETTE_CUSTOM) {
|
||||
configPlayerPalette = gPalettePresets[sPalettePresetIndex];
|
||||
djui_panel_player_edit_palette_update_palette_display();
|
||||
}
|
||||
|
||||
if (configPlayerModel >= CT_MAX) { configPlayerModel = 0; }
|
||||
if (gNetworkPlayers[0].overrideModelIndex == gNetworkPlayers[0].modelIndex) { gNetworkPlayers[0].overrideModelIndex = configPlayerModel; }
|
||||
if (gNetworkPlayers[0].overridePaletteIndex == gNetworkPlayers[0].paletteIndex) { gNetworkPlayers[0].overridePaletteIndex = configPlayerPalette; }
|
||||
|
||||
gNetworkPlayers[0].modelIndex = configPlayerModel;
|
||||
gNetworkPlayers[0].paletteIndex = configPlayerPalette;
|
||||
network_player_update_model(0);
|
||||
|
||||
if (gNetworkType != NT_NONE) {
|
||||
|
@ -53,7 +232,7 @@ void djui_panel_player_value_changed(UNUSED struct DjuiBase* caller) {
|
|||
}
|
||||
|
||||
void djui_panel_player_create(struct DjuiBase* caller) {
|
||||
f32 bodyHeight = 32 * 3 + 64 * 1 + 16 * 4;
|
||||
f32 bodyHeight = 32 * 3 + 64 * 2 + 16 * 5;
|
||||
|
||||
struct DjuiBase* defaultBase = NULL;
|
||||
struct DjuiThreePanel* panel = djui_panel_menu_create(bodyHeight, "\\#ff0800\\P\\#1be700\\L\\#00b3ff\\A\\#ffef00\\Y\\#ff0800\\E\\#1be700\\R");
|
||||
|
@ -93,7 +272,7 @@ void djui_panel_player_create(struct DjuiBase* caller) {
|
|||
djui_base_set_size(&selectionbox1->base, 1.0f, 32);
|
||||
djui_interactable_hook_value_change(&selectionbox1->base, djui_panel_player_value_changed);
|
||||
|
||||
char* paletteChoices[PALETTE_MAX] = {
|
||||
char* paletteChoices[PALETTE_PRESET_MAX+1] = {
|
||||
"Mario",
|
||||
"Luigi",
|
||||
"Waluigi",
|
||||
|
@ -126,11 +305,25 @@ void djui_panel_player_create(struct DjuiBase* caller) {
|
|||
"Bubblegum",
|
||||
"Ice Mario",
|
||||
"Ice Luigi",
|
||||
"Custom",
|
||||
};
|
||||
struct DjuiSelectionbox* selectionbox2 = djui_selectionbox_create(&body->base, "Palette", paletteChoices, PALETTE_MAX, &configPlayerPalette);
|
||||
djui_base_set_size_type(&selectionbox2->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_size(&selectionbox2->base, 1.0f, 32);
|
||||
djui_interactable_hook_value_change(&selectionbox2->base, djui_panel_player_value_changed);
|
||||
|
||||
for (int i = 0; i < PALETTE_PRESET_MAX; i++) {
|
||||
if (memcmp(&gNetworkPlayers[0].palette, &gPalettePresets[i], sizeof(struct PlayerPalette)) == 0) {
|
||||
sPalettePresetIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sPalettePresetSelection = djui_selectionbox_create(&body->base, "Palette Preset", paletteChoices, PALETTE_PRESET_MAX+1, &sPalettePresetIndex);
|
||||
djui_base_set_size_type(&sPalettePresetSelection->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_size(&sPalettePresetSelection->base, 1.0f, 32);
|
||||
djui_interactable_hook_value_change(&sPalettePresetSelection->base, djui_panel_player_value_changed);
|
||||
|
||||
struct DjuiButton* editPaletteButton = djui_button_create(&body->base, "Edit Palette");
|
||||
djui_base_set_size_type(&editPaletteButton->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_size(&editPaletteButton->base, 1.0f, 64);
|
||||
djui_interactable_hook_click(&editPaletteButton->base, djui_panel_player_edit_palette_create);
|
||||
|
||||
struct DjuiButton* button6 = djui_button_create(&body->base, "Back");
|
||||
djui_base_set_size_type(&button6->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
|
|
|
@ -45,18 +45,24 @@ static void djui_selectionbox_get_cursor_hover_location(struct DjuiBase* base, f
|
|||
*y = (rectBase->elem.y + rectBase->elem.height * 3.0f / 4.0f);
|
||||
}
|
||||
|
||||
void djui_selectionbox_update_value(struct DjuiBase* base) {
|
||||
struct DjuiSelectionbox* selectionbox = (struct DjuiSelectionbox*)base;
|
||||
djui_text_set_text(selectionbox->rectText, selectionbox->choices[*selectionbox->value]);
|
||||
}
|
||||
|
||||
static void djui_selectionbox_on_cursor_down_begin(struct DjuiBase* base, UNUSED bool inputCursor) {
|
||||
struct DjuiSelectionbox* selectionbox = (struct DjuiSelectionbox*)base;
|
||||
f32 x = selectionbox->rect->base.elem.x;
|
||||
if (gCursorX >= x) {
|
||||
*selectionbox->value = (*selectionbox->value + 1) % selectionbox->choiceCount;
|
||||
djui_text_set_text(selectionbox->rectText, selectionbox->choices[*selectionbox->value]);
|
||||
djui_selectionbox_update_value(base);
|
||||
if (base != NULL && base->interactable != NULL && base->interactable->on_value_change != NULL) {
|
||||
base->interactable->on_value_change(base);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void djui_selectionbox_destroy(struct DjuiBase* base) {
|
||||
struct DjuiSelectionbox* selectionbox = (struct DjuiSelectionbox*)base;
|
||||
for (int i = 0; i < selectionbox->choiceCount; i++) {
|
||||
|
|
|
@ -13,3 +13,4 @@ struct DjuiSelectionbox {
|
|||
};
|
||||
|
||||
struct DjuiSelectionbox* djui_selectionbox_create(struct DjuiBase* parent, const char* message, char* choices[], u8 choiceCount, unsigned int* value);
|
||||
void djui_selectionbox_update_value(struct DjuiBase* base);
|
|
@ -28,7 +28,7 @@ static void djui_slider_update_style(struct DjuiBase* base) {
|
|||
}
|
||||
}
|
||||
|
||||
static void djui_slider_update_value(struct DjuiBase* base) {
|
||||
void djui_slider_update_value(struct DjuiBase* base) {
|
||||
struct DjuiSlider* slider = (struct DjuiSlider*)base;
|
||||
u32 min = slider->min;
|
||||
u32 max = slider->max;
|
||||
|
|
|
@ -12,3 +12,4 @@ struct DjuiSlider {
|
|||
};
|
||||
|
||||
struct DjuiSlider* djui_slider_create(struct DjuiBase* parent, const char* message, unsigned int* value, unsigned int min, unsigned int max);
|
||||
void djui_slider_update_value(struct DjuiBase* base);
|
||||
|
|
|
@ -891,7 +891,7 @@ static struct LuaObjectField sModeTransitionInfoFields[LUA_MODE_TRANSITION_INFO_
|
|||
{ "transitionStart", LVT_COBJECT, offsetof(struct ModeTransitionInfo, transitionStart), true, LOT_LINEARTRANSITIONPOINT },
|
||||
};
|
||||
|
||||
#define LUA_NETWORK_PLAYER_FIELD_COUNT 25
|
||||
#define LUA_NETWORK_PLAYER_FIELD_COUNT 28
|
||||
static struct LuaObjectField sNetworkPlayerFields[LUA_NETWORK_PLAYER_FIELD_COUNT] = {
|
||||
{ "connected", LVT_BOOL, offsetof(struct NetworkPlayer, connected), true, LOT_NONE },
|
||||
{ "currActNum", LVT_S16, offsetof(struct NetworkPlayer, currActNum), true, LOT_NONE },
|
||||
|
@ -915,7 +915,10 @@ static struct LuaObjectField sNetworkPlayerFields[LUA_NETWORK_PLAYER_FIELD_COUNT
|
|||
{ "name", LVT_STRING, offsetof(struct NetworkPlayer, name), true, LOT_NONE },
|
||||
{ "onRxSeqId", LVT_U8, offsetof(struct NetworkPlayer, onRxSeqId), true, LOT_NONE },
|
||||
{ "overrideModelIndex", LVT_U8, offsetof(struct NetworkPlayer, overrideModelIndex), false, LOT_NONE },
|
||||
{ "overridePalette", LVT_COBJECT, offsetof(struct NetworkPlayer, overridePalette), false, LOT_PLAYERPALETTE },
|
||||
{ "overridePaletteIndex", LVT_U8, offsetof(struct NetworkPlayer, overridePaletteIndex), false, LOT_NONE },
|
||||
{ "overridePaletteIndexLp", LVT_U8, offsetof(struct NetworkPlayer, overridePaletteIndexLp), true, LOT_NONE },
|
||||
{ "palette", LVT_COBJECT, offsetof(struct NetworkPlayer, palette), true, LOT_PLAYERPALETTE },
|
||||
{ "paletteIndex", LVT_U8, offsetof(struct NetworkPlayer, paletteIndex), true, LOT_NONE },
|
||||
// { "rxPacketHash", LOT_???, offsetof(struct NetworkPlayer, rxPacketHash), true, LOT_??? }, <--- UNIMPLEMENTED
|
||||
// { "rxSeqIds", LOT_???, offsetof(struct NetworkPlayer, rxSeqIds), true, LOT_??? }, <--- UNIMPLEMENTED
|
||||
|
@ -1762,6 +1765,11 @@ static struct LuaObjectField sPlayerGeometryFields[LUA_PLAYER_GEOMETRY_FIELD_COU
|
|||
{ "waterHeight", LVT_F32, offsetof(struct PlayerGeometry, waterHeight), false, LOT_NONE },
|
||||
};
|
||||
|
||||
#define LUA_PLAYER_PALETTE_FIELD_COUNT 0
|
||||
static struct LuaObjectField sPlayerPaletteFields[LUA_PLAYER_PALETTE_FIELD_COUNT] = {
|
||||
// { "parts", LOT_???, offsetof(struct PlayerPalette, parts), false, LOT_??? }, <--- UNIMPLEMENTED
|
||||
};
|
||||
|
||||
#define LUA_RAY_INTERSECTION_INFO_FIELD_COUNT 2
|
||||
static struct LuaObjectField sRayIntersectionInfoFields[LUA_RAY_INTERSECTION_INFO_FIELD_COUNT] = {
|
||||
{ "hitPos", LVT_COBJECT, offsetof(struct RayIntersectionInfo, hitPos), true, LOT_VEC3F },
|
||||
|
@ -2026,6 +2034,7 @@ struct LuaObjectTable sLuaObjectAutogenTable[LOT_AUTOGEN_MAX - LOT_AUTOGEN_MIN]
|
|||
{ LOT_PARALLELTRACKINGPOINT, sParallelTrackingPointFields, LUA_PARALLEL_TRACKING_POINT_FIELD_COUNT },
|
||||
{ LOT_PLAYERCAMERASTATE, sPlayerCameraStateFields, LUA_PLAYER_CAMERA_STATE_FIELD_COUNT },
|
||||
{ LOT_PLAYERGEOMETRY, sPlayerGeometryFields, LUA_PLAYER_GEOMETRY_FIELD_COUNT },
|
||||
{ LOT_PLAYERPALETTE, sPlayerPaletteFields, LUA_PLAYER_PALETTE_FIELD_COUNT },
|
||||
{ LOT_RAYINTERSECTIONINFO, sRayIntersectionInfoFields, LUA_RAY_INTERSECTION_INFO_FIELD_COUNT },
|
||||
{ LOT_SERVERSETTINGS, sServerSettingsFields, LUA_SERVER_SETTINGS_FIELD_COUNT },
|
||||
{ LOT_SOUNDSTATE, sSoundStateFields, LUA_SOUND_STATE_FIELD_COUNT },
|
||||
|
|
|
@ -51,6 +51,7 @@ enum LuaObjectAutogenType {
|
|||
LOT_PARALLELTRACKINGPOINT,
|
||||
LOT_PLAYERCAMERASTATE,
|
||||
LOT_PLAYERGEOMETRY,
|
||||
LOT_PLAYERPALETTE,
|
||||
LOT_RAYINTERSECTIONINFO,
|
||||
LOT_SERVERSETTINGS,
|
||||
LOT_SOUNDSTATE,
|
||||
|
|
|
@ -1035,7 +1035,11 @@ char gSmluaConstants[] = ""
|
|||
"CAM_EVENT_START_ENDING = 11\n"
|
||||
"CAM_EVENT_START_END_WAVING = 12\n"
|
||||
"CAM_EVENT_START_CREDITS = 13\n"
|
||||
"PALETTE_MAX = 32\n"
|
||||
"PALETTE_PRESET_MAX = 32\n"
|
||||
"SHIRT = 0\n"
|
||||
"PANTS = 1\n"
|
||||
"GLOVES = 2\n"
|
||||
"PLAYER_PART_MAX = 3\n"
|
||||
"CT_MARIO = 0\n"
|
||||
"CT_LUIGI = 1\n"
|
||||
"CT_TOAD = 2\n"
|
||||
|
@ -1671,6 +1675,7 @@ char gSmluaConstants[] = ""
|
|||
"UNKNOWN_NETWORK_INDEX = (-1)\n"
|
||||
"NETWORK_PLAYER_TIMEOUT = 10\n"
|
||||
"MAX_RX_SEQ_IDS = 64\n"
|
||||
"USE_REAL_PALETTE_VAR = 0xFF\n"
|
||||
"NPT_UNKNOWN = 0\n"
|
||||
"NPT_LOCAL = 1\n"
|
||||
"NPT_SERVER = 2\n"
|
||||
|
|
|
@ -41,7 +41,7 @@ static void on_activity_join_callback(UNUSED void* data, enum EDiscordResult res
|
|||
|
||||
if (gNetworkType == NT_CLIENT) {
|
||||
if (gNetworkPlayerServer == NULL) {
|
||||
network_player_connected(NPT_SERVER, 0, 0, 0, "Player");
|
||||
network_player_connected(NPT_SERVER, 0, 0, &DEFAULT_MARIO_PALETTE, "Player");
|
||||
}
|
||||
ns_discord_save_id(gNetworkPlayerServer->localIndex, lobby->owner_id);
|
||||
network_send_mod_list_request();
|
||||
|
|
|
@ -127,7 +127,7 @@ bool network_init(enum NetworkType inNetworkType) {
|
|||
|
||||
dynos_behavior_hook_all_custom_behaviors();
|
||||
|
||||
network_player_connected(NPT_LOCAL, 0, configPlayerModel, configPlayerPalette, configPlayerName);
|
||||
network_player_connected(NPT_LOCAL, 0, configPlayerModel, &configPlayerPalette, configPlayerName);
|
||||
extern u8* gOverrideEeprom;
|
||||
gOverrideEeprom = NULL;
|
||||
|
||||
|
|
|
@ -19,9 +19,9 @@ static char sDefaultPlayerName[] = "Player";
|
|||
|
||||
void network_player_init(void) {
|
||||
gNetworkPlayers[0].modelIndex = (configPlayerModel < CT_MAX) ? configPlayerModel : 0;
|
||||
gNetworkPlayers[0].paletteIndex = configPlayerPalette;
|
||||
gNetworkPlayers[0].palette = configPlayerPalette;
|
||||
gNetworkPlayers[0].overrideModelIndex = gNetworkPlayers[0].modelIndex;
|
||||
gNetworkPlayers[0].overridePaletteIndex = gNetworkPlayers[0].paletteIndex;
|
||||
gNetworkPlayers[0].overridePalette = gNetworkPlayers[0].palette;
|
||||
}
|
||||
|
||||
void network_player_update_model(u8 localIndex) {
|
||||
|
@ -169,7 +169,7 @@ void network_player_update(void) {
|
|||
}
|
||||
}
|
||||
|
||||
u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex, u8 modelIndex, u8 paletteIndex, char *name) {
|
||||
u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex, u8 modelIndex, const struct PlayerPalette* palette, char *name) {
|
||||
// translate globalIndex to localIndex
|
||||
u8 localIndex = globalIndex;
|
||||
if (gNetworkType == NT_SERVER) {
|
||||
|
@ -198,9 +198,9 @@ u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex, u8 mode
|
|||
if ((type != NPT_LOCAL) && (gNetworkType == NT_SERVER || type == NPT_SERVER)) { gNetworkSystem->save_id(localIndex, 0); }
|
||||
|
||||
if (np->modelIndex == np->overrideModelIndex) { np->overrideModelIndex = modelIndex; }
|
||||
if (np->paletteIndex == np->overridePaletteIndex) { np->overridePaletteIndex = paletteIndex; }
|
||||
if (memcmp(&np->palette, &np->overridePalette, sizeof(struct PlayerPalette)) == 0) { np->overridePalette = *palette; }
|
||||
np->modelIndex = modelIndex;
|
||||
np->paletteIndex = paletteIndex;
|
||||
np->palette = *palette;
|
||||
network_player_update_model(localIndex);
|
||||
|
||||
snprintf(np->name, MAX_PLAYER_STRING, "%s", name);
|
||||
|
@ -228,9 +228,14 @@ u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex, u8 mode
|
|||
// update visuals
|
||||
np->fadeOpacity = 0;
|
||||
np->modelIndex = modelIndex;
|
||||
np->paletteIndex = paletteIndex;
|
||||
np->palette = *palette;
|
||||
np->overrideModelIndex = modelIndex;
|
||||
np->overridePaletteIndex = paletteIndex;
|
||||
np->overridePalette = *palette;
|
||||
|
||||
np->paletteIndex = USE_REAL_PALETTE_VAR;
|
||||
np->overridePaletteIndex = USE_REAL_PALETTE_VAR;
|
||||
np->overridePaletteIndexLp = USE_REAL_PALETTE_VAR;
|
||||
|
||||
snprintf(np->name, MAX_PLAYER_STRING, "%s", name);
|
||||
network_player_update_model(localIndex);
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#define UNKNOWN_NETWORK_INDEX ((u64)-1)
|
||||
#define NETWORK_PLAYER_TIMEOUT 10
|
||||
#define MAX_RX_SEQ_IDS 64
|
||||
#define USE_REAL_PALETTE_VAR 0xFF
|
||||
|
||||
enum NetworkPlayerType {
|
||||
NPT_UNKNOWN,
|
||||
|
@ -36,7 +37,7 @@ struct NetworkPlayer {
|
|||
u8 fadeOpacity;
|
||||
u8 onRxSeqId;
|
||||
u8 modelIndex;
|
||||
u8 paletteIndex;
|
||||
struct PlayerPalette palette;
|
||||
char name[MAX_PLAYER_STRING+1];
|
||||
|
||||
char description[MAX_DESCRIPTION_STRING+1];
|
||||
|
@ -46,10 +47,15 @@ struct NetworkPlayer {
|
|||
u8 descriptionA;
|
||||
|
||||
u8 overrideModelIndex;
|
||||
u8 overridePaletteIndex;
|
||||
struct PlayerPalette overridePalette;
|
||||
|
||||
u16 rxSeqIds[MAX_RX_SEQ_IDS];
|
||||
u32 rxPacketHash[MAX_RX_SEQ_IDS];
|
||||
|
||||
// legacy fields to allow mods not to break
|
||||
u8 paletteIndex;
|
||||
u8 overridePaletteIndex;
|
||||
u8 overridePaletteIndexLp;
|
||||
};
|
||||
|
||||
extern struct NetworkPlayer gNetworkPlayers[];
|
||||
|
@ -69,7 +75,7 @@ struct NetworkPlayer* get_network_player_smallest_global(void);
|
|||
|
||||
void network_player_update(void);
|
||||
|
||||
u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex, u8 modelIndex, u8 paletteIndex, char* name);
|
||||
u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex, u8 modelIndex, const struct PlayerPalette* playerPalette, char* name);
|
||||
u8 network_player_disconnected(u8 globalIndex);
|
||||
|
||||
void network_player_update_course_level(struct NetworkPlayer* np, s16 courseNum, s16 actNum, s16 levelNum, s16 areaIndex);
|
||||
|
|
|
@ -30,10 +30,9 @@ u8* network_get_player_text_color(u8 localIndex) {
|
|||
if (localIndex >= MAX_PLAYERS) { localIndex = 0; }
|
||||
|
||||
struct NetworkPlayer* np = &gNetworkPlayers[localIndex];
|
||||
u8* rgb = get_player_color(np->overridePaletteIndex, 0);
|
||||
static u8 sTextRgb[3] = { 0 };
|
||||
for (int i = 0; i < 3; i++) {
|
||||
sTextRgb[i] = 127 + rgb[i] / 2;
|
||||
sTextRgb[i] = 127 + np->overridePalette.parts[SHIRT][i] / 2;
|
||||
}
|
||||
|
||||
return sTextRgb;
|
||||
|
|
|
@ -26,7 +26,7 @@ extern u8* gOverrideEeprom;
|
|||
static u8 eeprom[512] = { 0 };
|
||||
|
||||
static u8 sJoinRequestPlayerModel;
|
||||
static u8 sJoinRequestPlayerPalette;
|
||||
static struct PlayerPalette sJoinRequestPlayerPalette;
|
||||
static char sJoinRequestPlayerName[MAX_PLAYER_STRING];
|
||||
|
||||
void network_send_join_request(void) {
|
||||
|
@ -39,7 +39,7 @@ void network_send_join_request(void) {
|
|||
packet_init(&p, PACKET_JOIN_REQUEST, true, PLMT_NONE);
|
||||
|
||||
packet_write(&p, &configPlayerModel, sizeof(u8));
|
||||
packet_write(&p, &configPlayerPalette, sizeof(u8));
|
||||
packet_write(&p, &configPlayerPalette, sizeof(struct PlayerPalette));
|
||||
packet_write(&p, &configPlayerName, sizeof(u8) * MAX_PLAYER_STRING);
|
||||
|
||||
network_send_to((gNetworkPlayerServer != NULL) ? gNetworkPlayerServer->localIndex : 0, &p);
|
||||
|
@ -52,11 +52,11 @@ void network_receive_join_request(struct Packet* p) {
|
|||
|
||||
if (p->dataLength > 5) {
|
||||
packet_read(p, &sJoinRequestPlayerModel, sizeof(u8));
|
||||
packet_read(p, &sJoinRequestPlayerPalette, sizeof(u8));
|
||||
packet_read(p, &sJoinRequestPlayerPalette, sizeof(struct PlayerPalette));
|
||||
packet_read(p, &sJoinRequestPlayerName, sizeof(u8) * MAX_PLAYER_STRING);
|
||||
} else {
|
||||
sJoinRequestPlayerModel = 0;
|
||||
sJoinRequestPlayerPalette = 0;
|
||||
sJoinRequestPlayerPalette = DEFAULT_MARIO_PALETTE;
|
||||
snprintf(sJoinRequestPlayerName, MAX_PLAYER_STRING, "%s", "Player");
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ void network_send_join(struct Packet* joinRequestPacket) {
|
|||
LOG_INFO("chose globalIndex: %d", globalIndex);
|
||||
|
||||
// do connection event
|
||||
network_player_connected(NPT_CLIENT, globalIndex, sJoinRequestPlayerModel, sJoinRequestPlayerPalette, sJoinRequestPlayerName);
|
||||
network_player_connected(NPT_CLIENT, globalIndex, sJoinRequestPlayerModel, &sJoinRequestPlayerPalette, sJoinRequestPlayerName);
|
||||
|
||||
fs_file_t* fp = fs_open(SAVE_FILENAME);
|
||||
if (fp != NULL) {
|
||||
|
@ -220,8 +220,8 @@ void network_receive_join(struct Packet* p) {
|
|||
}
|
||||
string_linked_list_free(&head);
|
||||
|
||||
network_player_connected(NPT_SERVER, 0, 0, 0, "Player");
|
||||
network_player_connected(NPT_LOCAL, myGlobalIndex, configPlayerModel, configPlayerPalette, configPlayerName);
|
||||
network_player_connected(NPT_SERVER, 0, 0, &DEFAULT_MARIO_PALETTE, "Player");
|
||||
network_player_connected(NPT_LOCAL, myGlobalIndex, configPlayerModel, &configPlayerPalette, configPlayerName);
|
||||
djui_chat_box_create();
|
||||
|
||||
save_file_load_all(TRUE);
|
||||
|
|
|
@ -33,7 +33,7 @@ static void network_send_to_network_players(u8 sendToLocalIndex) {
|
|||
packet_write(&p, &gNetworkPlayers[i].currAreaSyncValid, sizeof(u8));
|
||||
packet_write(&p, &networkId, sizeof(s64));
|
||||
packet_write(&p, &gNetworkPlayers[i].modelIndex, sizeof(u8));
|
||||
packet_write(&p, &gNetworkPlayers[i].paletteIndex, sizeof(u8));
|
||||
packet_write(&p, &gNetworkPlayers[i].palette, sizeof(struct PlayerPalette));
|
||||
packet_write(&p, &gNetworkPlayers[i].name, sizeof(u8) * MAX_PLAYER_STRING);
|
||||
LOG_INFO("send network player [%d == %d]", gNetworkPlayers[i].globalIndex, npType);
|
||||
}
|
||||
|
@ -89,7 +89,8 @@ void network_receive_network_players(struct Packet *p) {
|
|||
s16 courseNum, actNum, levelNum, areaIndex;
|
||||
u8 levelSyncValid, areaSyncValid;
|
||||
s64 networkId;
|
||||
u8 modelIndex, paletteIndex;
|
||||
u8 modelIndex;
|
||||
struct PlayerPalette palette;
|
||||
char playerName[MAX_PLAYER_STRING] = { 0 };
|
||||
|
||||
packet_read(p, &npType, sizeof(u8));
|
||||
|
@ -103,10 +104,10 @@ void network_receive_network_players(struct Packet *p) {
|
|||
packet_read(p, &areaSyncValid, sizeof(u8));
|
||||
packet_read(p, &networkId, sizeof(s64));
|
||||
packet_read(p, &modelIndex, sizeof(u8));
|
||||
packet_read(p, &paletteIndex, sizeof(u8));
|
||||
packet_read(p, &palette, sizeof(struct PlayerPalette));
|
||||
packet_read(p, &playerName, sizeof(u8) * MAX_PLAYER_STRING);
|
||||
|
||||
u8 localIndex = network_player_connected(npType, globalIndex, modelIndex, paletteIndex, playerName);
|
||||
u8 localIndex = network_player_connected(npType, globalIndex, modelIndex, &palette, playerName);
|
||||
LOG_INFO("received network player [%d == %d] (%d)", globalIndex, npType, localIndex);
|
||||
if (localIndex != UNKNOWN_GLOBAL_INDEX) {
|
||||
struct NetworkPlayer *np = &gNetworkPlayers[localIndex];
|
||||
|
@ -121,7 +122,7 @@ void network_receive_network_players(struct Packet *p) {
|
|||
}
|
||||
} else {
|
||||
np->modelIndex = (modelIndex < CT_MAX) ? modelIndex : 0;
|
||||
np->paletteIndex = paletteIndex;
|
||||
np->palette = palette;
|
||||
network_player_update_model(localIndex);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ void network_send_player_settings(void) {
|
|||
packet_write(&p, &gNetworkPlayers[0].globalIndex, sizeof(u8));
|
||||
packet_write(&p, playerName, MAX_PLAYER_STRING * sizeof(u8));
|
||||
packet_write(&p, &configPlayerModel, sizeof(u8));
|
||||
packet_write(&p, &configPlayerPalette, sizeof(u8));
|
||||
packet_write(&p, &configPlayerPalette, sizeof(struct PlayerPalette));
|
||||
|
||||
if (gNetworkPlayerLocal != NULL) {
|
||||
if (snprintf(gNetworkPlayerLocal->name, MAX_PLAYER_STRING, "%s", playerName) < 0) {
|
||||
|
@ -28,12 +28,12 @@ void network_receive_player_settings(struct Packet* p) {
|
|||
u8 globalId;
|
||||
char playerName[MAX_PLAYER_STRING+1] = { 0 };
|
||||
u8 playerModel;
|
||||
u8 playerPalette;
|
||||
struct PlayerPalette playerPalette;
|
||||
|
||||
packet_read(p, &globalId, sizeof(u8));
|
||||
packet_read(p, &playerName, MAX_PLAYER_STRING * sizeof(u8));
|
||||
packet_read(p, &playerModel, sizeof(u8));
|
||||
packet_read(p, &playerPalette, sizeof(u8));
|
||||
packet_read(p, &playerPalette, sizeof(struct PlayerPalette));
|
||||
|
||||
if (globalId == gNetworkPlayers[0].globalIndex || globalId > MAX_PLAYERS) {
|
||||
LOG_ERROR("Received player settings from improper player.");
|
||||
|
@ -48,7 +48,6 @@ void network_receive_player_settings(struct Packet* p) {
|
|||
|
||||
// sanity check
|
||||
if (playerModel >= CT_MAX) { playerModel = CT_MARIO; }
|
||||
if (playerPalette >= PALETTE_MAX) { playerPalette = 0; }
|
||||
|
||||
struct NetworkPlayer* np = network_player_from_global_index(globalId);
|
||||
if (snprintf(np->name, MAX_PLAYER_STRING, "%s", playerName) < 0) {
|
||||
|
@ -56,10 +55,10 @@ void network_receive_player_settings(struct Packet* p) {
|
|||
}
|
||||
|
||||
if (np->modelIndex == np->overrideModelIndex) { np->overrideModelIndex = playerModel; }
|
||||
if (np->paletteIndex == np->overridePaletteIndex) { np->overridePaletteIndex = playerPalette; }
|
||||
if (memcmp(&np->palette, &np->overridePalette, sizeof(struct PlayerPalette)) == 0) { np->overridePalette = playerPalette; }
|
||||
|
||||
np->modelIndex = playerModel;
|
||||
np->paletteIndex = playerPalette;
|
||||
np->palette = playerPalette;
|
||||
|
||||
network_player_update_model(np->localIndex);
|
||||
}
|
||||
|
|
|
@ -316,7 +316,6 @@ void main_func(void) {
|
|||
dynos_pack_init();
|
||||
|
||||
if (configPlayerModel >= CT_MAX) { configPlayerModel = 0; }
|
||||
if (configPlayerPalette >= PALETTE_MAX) { configPlayerPalette = 0; }
|
||||
|
||||
if (gCLIOpts.FullScreen == 1)
|
||||
configWindow.fullscreen = true;
|
||||
|
|
Loading…
Reference in a new issue