|
|
1.1 root 1: #include "g_local.h"
2:
3: // Note that the pmenu entries are duplicated
4: // this is so that a static set of pmenu entries can be used
5: // for multiple clients and changed without interference
6: // note that arg will be freed when the menu is closed, it must be allocated memory
7: pmenuhnd_t *PMenu_Open(edict_t *ent, pmenu_t *entries, int cur, int num, void *arg)
8: {
9: pmenuhnd_t *hnd;
10: pmenu_t *p;
11: int i;
12:
13: if (!ent->client)
14: return NULL;
15:
16: if (ent->client->menu) {
17: gi.dprintf("warning, ent already has a menu\n");
18: PMenu_Close(ent);
19: }
20:
21: hnd = malloc(sizeof(*hnd));
22:
23: hnd->arg = arg;
24: hnd->entries = malloc(sizeof(pmenu_t) * num);
25: memcpy(hnd->entries, entries, sizeof(pmenu_t) * num);
26: // duplicate the strings since they may be from static memory
27: for (i = 0; i < num; i++)
28: if (entries[i].text)
29: hnd->entries[i].text = strdup(entries[i].text);
30:
31: hnd->num = num;
32:
33: if (cur < 0 || !entries[cur].SelectFunc) {
34: for (i = 0, p = entries; i < num; i++, p++)
35: if (p->SelectFunc)
36: break;
37: } else
38: i = cur;
39:
40: if (i >= num)
41: hnd->cur = -1;
42: else
43: hnd->cur = i;
44:
45: ent->client->showscores = true;
46: ent->client->inmenu = true;
47: ent->client->menu = hnd;
48:
49: PMenu_Do_Update(ent);
50: gi.unicast (ent, true);
51:
52: return hnd;
53: }
54:
55: void PMenu_Close(edict_t *ent)
56: {
57: int i;
58: pmenuhnd_t *hnd;
59:
60: if (!ent->client->menu)
61: return;
62:
63: hnd = ent->client->menu;
64: for (i = 0; i < hnd->num; i++)
65: if (hnd->entries[i].text)
66: free(hnd->entries[i].text);
67: free(hnd->entries);
68: if (hnd->arg)
69: free(hnd->arg);
70: free(hnd);
71: ent->client->menu = NULL;
72: ent->client->showscores = false;
73: }
74:
75: // only use on pmenu's that have been called with PMenu_Open
76: void PMenu_UpdateEntry(pmenu_t *entry, const char *text, int align, SelectFunc_t SelectFunc)
77: {
78: if (entry->text)
79: free(entry->text);
80: entry->text = strdup(text);
81: entry->align = align;
82: entry->SelectFunc = SelectFunc;
83: }
84:
85: void PMenu_Do_Update(edict_t *ent)
86: {
87: char string[1400];
88: int i;
89: pmenu_t *p;
90: int x;
91: pmenuhnd_t *hnd;
92: char *t;
93: qboolean alt = false;
94:
95: if (!ent->client->menu) {
96: gi.dprintf("warning: ent has no menu\n");
97: return;
98: }
99:
100: hnd = ent->client->menu;
101:
102: strcpy(string, "xv 32 yv 8 picn inventory ");
103:
104: for (i = 0, p = hnd->entries; i < hnd->num; i++, p++) {
105: if (!p->text || !*(p->text))
106: continue; // blank line
107: t = p->text;
108: if (*t == '*') {
109: alt = true;
110: t++;
111: }
112: sprintf(string + strlen(string), "yv %d ", 32 + i * 8);
113: if (p->align == PMENU_ALIGN_CENTER)
114: x = 196/2 - strlen(t)*4 + 64;
115: else if (p->align == PMENU_ALIGN_RIGHT)
116: x = 64 + (196 - strlen(t)*8);
117: else
118: x = 64;
119:
120: sprintf(string + strlen(string), "xv %d ",
121: x - ((hnd->cur == i) ? 8 : 0));
122:
123: if (hnd->cur == i)
124: sprintf(string + strlen(string), "string2 \"\x0d%s\" ", t);
125: else if (alt)
126: sprintf(string + strlen(string), "string2 \"%s\" ", t);
127: else
128: sprintf(string + strlen(string), "string \"%s\" ", t);
129: alt = false;
130: }
131:
132: gi.WriteByte (svc_layout);
133: gi.WriteString (string);
134: }
135:
136: void PMenu_Update(edict_t *ent)
137: {
138: if (!ent->client->menu) {
139: gi.dprintf("warning: ent has no menu\n");
140: return;
141: }
142:
143: if (level.time - ent->client->menutime >= 1.0) {
144: // been a second or more since last update, update now
145: PMenu_Do_Update(ent);
146: gi.unicast (ent, true);
147: ent->client->menutime = level.time;
148: ent->client->menudirty = false;
149: }
150: ent->client->menutime = level.time + 0.2;
151: ent->client->menudirty = true;
152: }
153:
154: void PMenu_Next(edict_t *ent)
155: {
156: pmenuhnd_t *hnd;
157: int i;
158: pmenu_t *p;
159:
160: if (!ent->client->menu) {
161: gi.dprintf("warning: ent has no menu\n");
162: return;
163: }
164:
165: hnd = ent->client->menu;
166:
167: if (hnd->cur < 0)
168: return; // no selectable entries
169:
170: i = hnd->cur;
171: p = hnd->entries + hnd->cur;
172: do {
173: i++, p++;
174: if (i == hnd->num)
175: i = 0, p = hnd->entries;
176: if (p->SelectFunc)
177: break;
178: } while (i != hnd->cur);
179:
180: hnd->cur = i;
181:
182: PMenu_Update(ent);
183: }
184:
185: void PMenu_Prev(edict_t *ent)
186: {
187: pmenuhnd_t *hnd;
188: int i;
189: pmenu_t *p;
190:
191: if (!ent->client->menu) {
192: gi.dprintf("warning: ent has no menu\n");
193: return;
194: }
195:
196: hnd = ent->client->menu;
197:
198: if (hnd->cur < 0)
199: return; // no selectable entries
200:
201: i = hnd->cur;
202: p = hnd->entries + hnd->cur;
203: do {
204: if (i == 0) {
205: i = hnd->num - 1;
206: p = hnd->entries + i;
207: } else
208: i--, p--;
209: if (p->SelectFunc)
210: break;
211: } while (i != hnd->cur);
212:
213: hnd->cur = i;
214:
215: PMenu_Update(ent);
216: }
217:
218: void PMenu_Select(edict_t *ent)
219: {
220: pmenuhnd_t *hnd;
221: pmenu_t *p;
222:
223: if (!ent->client->menu) {
224: gi.dprintf("warning: ent has no menu\n");
225: return;
226: }
227:
228: hnd = ent->client->menu;
229:
230: if (hnd->cur < 0)
231: return; // no selectable entries
232:
233: p = hnd->entries + hnd->cur;
234:
235: if (p->SelectFunc)
236: p->SelectFunc(ent, hnd);
237: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.