summaryrefslogtreecommitdiff
path: root/src/code/m_snowman.c
blob: e55229a1ef2e2e90a66a18261fcb9419f36f298b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/**
 * @file m_snowman.c
 *
 * Manages data associated with snowmen.
 *
 * This data is stored in the SnowmanData struct in the save file.
 * There can be three snowmen built at a single time. Each snowman has 3 variations depending on how melted they are.
 * The first snowman uses the names SNOWMAN0, SNOWMAN1, and SNOWMAN2, the second snowman uses SNOWMAN3, SNOWMAN4, and
 * SNOWMAN5, etc.
 *
 */

#include "global.h"
#include "m_snowman.h"
#include "m_common_data.h"
#include "m_field_info.h"
#include "m_police_box.h"
#include "m_lib.h"
#include "libc64/qrand.h"
#include "m_name_table.h"

/**
 * After advancing daysElapsed days, is the snowman completely melted?
 *
 * @return True if the snowman is alive, False if the snowman is dead.
 */
s32 mSN_check_life(u16* name, s32 daysElapsed) {
    s32 ret = false;

    // Snowmen outside of winter die regardless of daysElapsed.
    if (common_data.time.season == WINTER) {
        s32 snowmanAge = ((*name - SNOWMAN0) % SNOWMAN_SAVE_COUNT);

        if (snowmanAge + daysElapsed < 3) {
            ret = true;
        }
    }

    return ret;
}

void mSN_ClearSnowmanData(u16* name, s32 snowmanIndex) {
    bzero(&common_data.save.snowmanData[snowmanIndex], sizeof(SnowmanData));
    *name = 0;
}

s32 mSN_ClearSnowman(u16* name) {
    s32 ret = 0;

    if ((*name >= SNOWMAN0) && (*name <= SNOWMAN8)) {
        s32 snowmanIndex = (*name - SNOWMAN0) / SNOWMAN_SAVE_COUNT;

        mSN_ClearSnowmanData(name, snowmanIndex);
        ret = 1;
    }

    return ret;
}

/**
 * Modify a snowman according to how many days have passed.
 *
 * @return 0 if the actor isn't a snowman. 1 if the actor is a snowman.
 */
s32 mSN_MeltSnowman(u16* name, s32 daysElapsed) {
    s32 ret = 0;

    if ((*name >= SNOWMAN0) && (*name <= SNOWMAN8)) {
        s32 snowmanIndex = (*name - SNOWMAN0) / SNOWMAN_SAVE_COUNT;

        if (daysElapsed < 0) {
            daysElapsed = 1;
            common_data.save.snowmanYear = 0;
            common_data.save.snowmanMonth = 0;
            common_data.save.snowmanDay = 0;
            common_data.save.snowmanHour = 0;
        }

        if (!mSN_check_life(name, daysElapsed)) {
            mSN_ClearSnowmanData(name, snowmanIndex);

        } else {
            SnowmanData* snowmanData = &common_data.save.snowmanData[snowmanIndex];

            *name += daysElapsed;

            while (daysElapsed) {
                snowmanData->headSize = (u8)(s32)(snowmanData->headSize * 0.8f);
                snowmanData->bodySize = (u8)(s32)(snowmanData->bodySize * 0.8f);
                daysElapsed--;
            }
        }

        ret = 1;
    }

    return ret;
}

/**
 * Find a slot in SnowmanData that isn't occupied by a snowman.
 *
 * @return the index of the first empty slot. If there are no empty slots, return -1.
 */
s32 mSN_get_free_space(void) {
    SnowmanData* snowmanData = common_data.save.snowmanData;
    s32 snowmanIndex;

    for (snowmanIndex = 0; snowmanIndex < SNOWMAN_SAVE_COUNT; snowmanIndex++) {
        if (!snowmanData[snowmanIndex].exists) {
            return snowmanIndex;
        }
    }

    return -1;
}

void mSN_regist_snowman_society(SnowmanInfo* snowmanInfo) {
    u16 sp2E = *mFI_GetUnitFG(snowmanInfo->position);
    s32 snowmanIndex = mSN_get_free_space();
    u16 name;

    if (snowmanIndex != -1) {
        mem_copy((u8*)&common_data.save.snowmanData[snowmanIndex], (u8*)snowmanInfo, sizeof(SnowmanData));

        if (sp2E) {
            mPB_keep_item(sp2E);
            mFI_Wpos2DepositOFF(snowmanInfo->position);
        }

        name = snowmanIndex * SNOWMAN_SAVE_COUNT + SNOWMAN0;
        mFI_SetFG_common(name, snowmanInfo->position, 1);
    }
}

void mSN_decide_msg(void) {
    common_data.unk_1074C = fqrand() * 3.0f;
}

void mSN_snowman_init(void) {
    bzero(common_data.save.snowmanData, sizeof(SnowmanData[SNOWMAN_SAVE_COUNT]));
    mSN_decide_msg();
}