|
|
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.