Simple Cusom Maplist
Moderator: InsideQC Admins
8 posts
• Page 1 of 1
Simple Cusom Maplist
Here my code for a Simple Custom Maplist for Quake
First we have to define the new menu, add m_maplist after m_gameoptions
in the enum {...}
now we define the menu voids:
void M_Menu_MapList_f (void);
void M_MapList_Draw (void);
void M_MapList_Key (int key);
so at first we have defined all new menus
now an copy&past code add it after "void M_GameOptions_Key (int key)":
now we have to add small code in "M_Init", "M_Draw", "M_Keydown".
"M_Init" add:
Cmd_AddCommand ("menu_maplist", M_Menu_MapList_f);
"M_Draw"
case m_maplist:
M_MapList_Draw ();
break;
"M_Keydown" add:
case m_maplist:
M_MapList_Key (key);
return;
now we have an working Custom maplist.
First we have to define the new menu, add m_maplist after m_gameoptions
in the enum {...}
now we define the menu voids:
void M_Menu_MapList_f (void);
void M_MapList_Draw (void);
void M_MapList_Key (int key);
so at first we have defined all new menus
now an copy&past code add it after "void M_GameOptions_Key (int key)":
- Code: Select all
//=============================================================================
/* MAPLIST MENU */
#include <sys/dirent.h>
#define MAX_FILE_LIST 15
int initState = 1;
int numFiles = 0;
int minFile = 0;
int maxFile = MAX_FILE_LIST;
struct dirent **nombres;
char listaFiles[MAX_FILE_LIST][256];
char nombreFile[MAX_FILE_LIST];
int arrowY = 35;
int posArrow = 0;
int numFileList = 0;
int lastArrowY = 0;
void DeleteArray (char listaFiles[MAX_FILE_LIST][256], int numFileList) {
int i;
for (i = 0; i < numFileList; i++)
strcpy(listaFiles[i], "0");
}
void FileNames (char listaFiles[MAX_FILE_LIST][256], int numFileList) {
int y = 35;
int i;
for(i = 0; i < numFileList; i++) {
M_Print (74, y, listaFiles[i]);
y += 8;
}
}
int isFile(const struct dirent *nombre) {
int isFile = 0;
char *extension = strrchr(nombre->d_name, '.');
if (strcmp(extension, ".bsp") == 0)
isFile = 1;
return isFile;
}
void M_Menu_MapList_f (void)
{
key_dest = key_menu;
m_state = m_maplist;
m_entersound = true;
if(initState) {
numFiles = scandir(va("%s/maps", GAMENAME), &nombres, isFile, alphasort);
if (numFiles < MAX_FILE_LIST) {
maxFile = numFiles;
numFileList = numFiles;
} else
numFileList = MAX_FILE_LIST;
DeleteArray(listaFiles, numFileList);
int x = 0;
int i;
for (i = minFile; i < maxFile; i++){
strcpy(listaFiles[x], nombres[i]->d_name);
x++;
}
initState = 0;
}
}
void M_MapList_Draw (void)
{
qpic_t *p;
int x;
M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
p = Draw_CachePic ("gfx/p_multi.lmp");
M_DrawPic ( (320-p->width)/2, 4, p);
M_DrawTextBox (56, 27, 23, 15);
if (!numFileList) {
M_PrintWhite (104, 59, "Empty Map list");
return;
} else
FileNames(listaFiles, numFileList);
M_DrawCharacter (64, arrowY, 12 + ((int)(realtime * 4) & 1));
}
void M_MapList_Key (int key)
{
switch (key)
{
case K_ESCAPE:
M_Menu_GameOptions_f ();
break;
case K_UPARROW:
S_LocalSound ("misc/menu1.wav");
arrowY -= 8;
posArrow--;
if (posArrow < 0) {
if (minFile != 0) {
minFile--;
maxFile--;
DeleteArray(listaFiles, numFileList);
int x = 0;
int i;
for (i = minFile; i < maxFile; i++) {
strcpy(listaFiles[x], nombres[i]->d_name);
x++;
}
}
arrowY = 35;
posArrow = 0;
}
break;
case K_DOWNARROW:
S_LocalSound ("misc/menu1.wav");
lastArrowY = arrowY;
arrowY += 8;
if (posArrow > numFileList-2) {
if(maxFile+1 <= numFiles) {
minFile++;
maxFile++;
DeleteArray(listaFiles, numFileList);
int x = 0;
int i;
for (i = minFile; i < maxFile; i++) {
strcpy(listaFiles[x], nombres[i]->d_name);
x++;
}
}
arrowY = lastArrowY;
} else
posArrow++;
break;
case K_ENTER:
S_LocalSound ("misc/menu2.wav");
strcpy(nombreFile, listaFiles[posArrow]);
COM_StripExtension (nombreFile, nombreFile);
COM_StripExtension (nombreFile, nombreFile);
Cbuf_AddText (va("map %s\n", nombreFile));
break;
}
}
now we have to add small code in "M_Init", "M_Draw", "M_Keydown".
"M_Init" add:
Cmd_AddCommand ("menu_maplist", M_Menu_MapList_f);
"M_Draw"
case m_maplist:
M_MapList_Draw ();
break;
"M_Keydown" add:
case m_maplist:
M_MapList_Key (key);
return;
now we have an working Custom maplist.
Last edited by Rikku2000 on Sat Jan 28, 2012 11:45 am, edited 3 times in total.
I am sorry for my English...
-

Rikku2000 - Posts: 49
- Joined: Wed Oct 20, 2010 6:33 pm
- Location: Germany
Re: Simple Cusom Maplist
Thank you Rikku2000 for posting this tutorial! Unfortunately I couldn't find how to make it work 
On windows msvc didn't find dirent.h in my sys so I had to download here and redefine it like this
and comment the part where it includes <machine/ansi.h>
Anyway I tried to follow all the steps as you wrote but it gave me a lot of errors. Since I use the italian version of MSVC2008 Express I'll try to translate them!
Pwhew! There were a lot!
This is the file I modified ( I can't post it here because its more of 60000 lines)
And this is the dirent.h
Keep in mind that I'm a SuperNoooob!
EDIT: I couldn't find M_Keydown. Are you sure it wasn't M_KeyEvent?
On windows msvc didn't find dirent.h in my sys so I had to download here and redefine it like this
- Code: Select all
#include "sys/dirent.h"
and comment the part where it includes <machine/ansi.h>
Anyway I tried to follow all the steps as you wrote but it gave me a lot of errors. Since I use the italian version of MSVC2008 Express I'll try to translate them!
- Code: Select all
1>Compiling...
1>menu.c
1>.\menu.c(4418) : warning C4013: 'DO_NOT_USE_STRCPY__USE_STRLCPY_OR_MEMCPY' non definied. It will be treated like an external one which returns an int.
1>.\menu.c(4446) : error C2065: 'm_maplist': identifier not declared
1>.\menu.c(4450) : warning C4013: 'scandir' non definied. It will be treated like an external one which returns an int.
1>.\menu.c(4450) : warning C4047: 'function': 'size_t' differs from 'char [4]' in the levels of indirect reference
1>.\menu.c(4450) : warning C4024: 'va': different types from formal parameter 2 and the effective one
1>.\menu.c(4450) : error C2198: 'va': insufficient arguments for a call
1>.\menu.c(4450) : error C2065: 'alphasort': identifier not declared
1>.\menu.c(4460) : error C2143: syntax error: ';' missed before 'type'
1>.\menu.c(4461) : error C2143: syntax error: ';' missed before 'type'
1>.\menu.c(4463) : error C2065: 'i': identifier not declared
1>.\menu.c(4463) : error C2065: 'i': identifier not declared
1>.\menu.c(4463) : error C2065: 'i': identifier not declared
1>.\menu.c(4464) : error C2065: 'x': identifier not declared
1>.\menu.c(4464) : error C2065: 'i': identifier not declared
1>.\menu.c(4465) : error C2065: 'x': identifier not declared
1>.\menu.c(4474) : error C2065: 'qpic_t': identifier not declared
1>.\menu.c(4474) : error C2065: 'p': identifier not declared
1>.\menu.c(4474) : warning C4552: '*': the operator has no effect. It was expected the operator with collateral effect.
1>.\menu.c(4475) : error C2143: syntax error: ';' missed before 'type'
1>.\menu.c(4477) : warning C4013: 'M_DrawTransPic' non definied. It will be treated like an external one which returns an int.
1>.\menu.c(4478) : error C2065: 'p': identifier not declared
1>.\menu.c(4478) : warning C4047: '=': 'int' differs from 'cachepic_t *' in the levels of indirect reference
1>.\menu.c(4479) : error C2065: 'p': identifier not declared
1>.\menu.c(4479) : error C2223: the element on the left of i '->width' must point to a struct/union
1>.\menu.c(4479) : error C2065: 'p': identifier not declared
1>.\menu.c(4479) : error C2198: 'M_DrawPic': insufficient arguments for a call
1>.\menu.c(4507) : error C2143: syntax error: ';' missed before 'type'
1>.\menu.c(4508) : error C2143: syntax error: ';' missed before 'type'
1>.\menu.c(4510) : error C2065: 'i': identifier not declared
1>.\menu.c(4510) : error C2065: 'i': identifier not declared
1>.\menu.c(4510) : error C2065: 'i': identifier not declared
1>.\menu.c(4511) : error C2065: 'x': identifier not declared
1>.\menu.c(4511) : error C2065: 'i': identifier not declared
1>.\menu.c(4512) : error C2065: 'x': identifier not declared
1>.\menu.c(4533) : error C2143: syntax error: ';' missed before 'type'
1>.\menu.c(4534) : error C2143: syntax error: ';' missed before 'type'
1>.\menu.c(4536) : error C2065: 'i': identifier not declared
1>.\menu.c(4536) : error C2065: 'i': identifier not declared
1>.\menu.c(4536) : error C2065: 'i': identifier not declared
1>.\menu.c(4537) : error C2065: 'x': identifier not declared
1>.\menu.c(4537) : error C2065: 'i': identifier not declared
1>.\menu.c(4538) : error C2065: 'x': identifier not declared
1>.\menu.c(4549) : warning C4013: 'DO_NOT_USE_STRCAT__USE_STRLCAT_OR_MEMCPY' non definied. It will be treated like an external one which returns an int.
1>.\menu.c(4550) : warning C4047: 'funzione': 'size_t' differs from 'char *' in the levels of indirect reference
1>.\menu.c(4550) : warning C4024: 'va': different types from formal parameter 2 and the effective one
1>.\menu.c(4550) : error C2198: 'va': insufficient arguments for a call
1>.\menu.c(4921) : error C2198: 'Cmd_AddCommand': insufficient arguments for a call
1>.\menu.c(5022) : error C2065: 'm_maplist': identifier not declared
1>.\menu.c(5022) : error C2051: expression case not constant
Pwhew! There were a lot!
This is the file I modified ( I can't post it here because its more of 60000 lines)
And this is the dirent.h
- Code: Select all
/*-
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)dirent.h 8.3 (Berkeley) 8/10/94
* $FreeBSD: src/sys/sys/dirent.h,v 1.11 1999/12/29 04:24:39 peter Exp $
*/
#ifndef _SYS_DIRENT_H_
#define _SYS_DIRENT_H_
//#include <machine/ansi.h>
/*
* The dirent structure defines the format of directory entries returned by
* the getdirentries(2) system call.
*
* A directory entry has a struct dirent at the front of it, containing its
* inode number, the length of the entry, and the length of the name
* contained in the entry. These are followed by the name padded to a 4
* byte boundary with null bytes. All names are guaranteed null terminated.
* The maximum length of a name in a directory is MAXNAMLEN.
*/
struct dirent {
int d_fileno;
int d_reclen;
int d_type;
int d_namlen;
#ifdef _POSIX_SOURCE
char d_name[255 + 1];
#else
#define MAXNAMLEN 255
char d_name[MAXNAMLEN + 1];
#endif
};
/*
* File types
*/
#define DT_UNKNOWN 0
#define DT_FIFO 1
#define DT_CHR 2
#define DT_DIR 4
#define DT_BLK 6
#define DT_REG 8
#define DT_LNK 10
#define DT_SOCK 12
#define DT_WHT 14
/*
* Convert between stat structure types and directory types.
*/
#define IFTODT(mode) (((mode) & 0170000) >> 12)
#define DTTOIF(dirtype) ((dirtype) << 12)
/*
* The _GENERIC_DIRSIZ macro gives the minimum record length which will hold
* the directory entry. This requires the amount of space in struct direct
* without the d_name field, plus enough space for the name with a terminating
* null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
*/
#define _GENERIC_DIRSIZ(dp) \
((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
#ifdef _KERNEL
#define GENERIC_DIRSIZ(dp) _GENERIC_DIRSIZ(dp)
#endif
#endif /* !_SYS_DIRENT_H_ */
Keep in mind that I'm a SuperNoooob!
EDIT: I couldn't find M_Keydown. Are you sure it wasn't M_KeyEvent?
Meadow Fun!! - my first commercial game, made with FTEQW game engine
- toneddu2000
- Posts: 1352
- Joined: Tue Feb 24, 2009 4:39 pm
- Location: Italy
Re: Simple Cusom Maplist
I things its kind of my compiler hehe becouse i use cygwin and edit the sys/dirent a bit hehe here my sys/dirent.h:
and the dirent.h in include dir:
- Code: Select all
/* Posix dirent.h for WIN32.
Copyright 2001, 2002, 2003, 2005, 2006, 2007, 2010 Red Hat, Inc.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
/* Including this file should not require any Windows headers. */
#ifndef _SYS_DIRENT_H
#define _SYS_DIRENT_H
#include <sys/types.h>
#include <limits.h>
#define direct dirent
#define __DIRENT_VERSION 2
#pragma pack(push,4)
#define _DIRENT_HAVE_D_TYPE
struct dirent
{
long __d_version; /* Used internally */
__ino64_t d_ino;
unsigned char d_type;
unsigned char __d_unused1[3];
__uint32_t __d_internal1;
char d_name[NAME_MAX + 1];
};
#pragma pack(pop)
#define __DIRENT_COOKIE 0xdede4242
#pragma pack(push,4)
typedef struct __DIR
{
/* This is first to set alignment in non _COMPILING_NEWLIB case. */
unsigned long __d_cookie;
struct dirent *__d_dirent;
char *__d_dirname; /* directory name with trailing '*' */
_off_t __d_position; /* used by telldir/seekdir */
int __d_fd;
unsigned __d_internal;
void *__handle;
void *__fh;
unsigned __flags;
} DIR;
#pragma pack(pop)
DIR *opendir (const char *);
DIR *fdopendir (int);
struct dirent *readdir (DIR *);
int readdir_r (DIR *, struct dirent *, struct dirent **);
void rewinddir (DIR *);
int closedir (DIR *);
int dirfd (DIR *);
#ifndef _POSIX_SOURCE
#ifndef __INSIDE_CYGWIN__
off_t telldir (DIR *);
void seekdir (DIR *, off_t loc);
#endif
int scandir (const char *__dir,
struct dirent ***__namelist,
int (*select) (const struct dirent *),
int (*compar) (const struct dirent **, const struct dirent **));
int alphasort (const struct dirent **__a, const struct dirent **__b);
#ifdef _DIRENT_HAVE_D_TYPE
/* File types for `d_type'. */
enum
{
DT_UNKNOWN = 0,
# define DT_UNKNOWN DT_UNKNOWN
DT_FIFO = 1,
# define DT_FIFO DT_FIFO
DT_CHR = 2,
# define DT_CHR DT_CHR
DT_DIR = 4,
# define DT_DIR DT_DIR
DT_BLK = 6,
# define DT_BLK DT_BLK
DT_REG = 8,
# define DT_REG DT_REG
DT_LNK = 10,
# define DT_LNK DT_LNK
DT_SOCK = 12,
# define DT_SOCK DT_SOCK
DT_WHT = 14
# define DT_WHT DT_WHT
};
/* Convert between stat structure types and directory types. */
# define IFTODT(mode) (((mode) & 0170000) >> 12)
# define DTTOIF(dirtype) ((dirtype) << 12)
#endif /* _DIRENT_HAVE_D_TYPE */
#endif /* _POSIX_SOURCE */
#endif /*_SYS_DIRENT_H*/
and the dirent.h in include dir:
- Code: Select all
#ifndef _DIRENT_H_
#define _DIRENT_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/dirent.h>
#if !defined(MAXNAMLEN) && !defined(_POSIX_SOURCE)
#define MAXNAMLEN 1024
#endif
#ifdef __cplusplus
}
#endif
#endif /*_DIRENT_H_*/
I am sorry for my English...
-

Rikku2000 - Posts: 49
- Joined: Wed Oct 20, 2010 6:33 pm
- Location: Germany
Re: Simple Cusom Maplist
Thanks for this tute. It's a great idea. Got it to work with two changes:
1. changed "strcat" to "strcpy" here- strcpy(nombreFile, listaFiles[posArrow]); Otherwise would add new map name onto the old map name.
2. I use mingw to compile for Windows. Unlike Linux gcc, mingw doesn't come with implementation of scandir, so I pasted in source for it. Don't know if would help MSVC2008 issue
1. changed "strcat" to "strcpy" here- strcpy(nombreFile, listaFiles[posArrow]); Otherwise would add new map name onto the old map name.
2. I use mingw to compile for Windows. Unlike Linux gcc, mingw doesn't come with implementation of scandir, so I pasted in source for it. Don't know if would help MSVC2008 issue
- Code: Select all
#include<stdlib.h>
#include<sys/types.h>
//qbism - needed for Rikku2000 maplist, but not included w/ mingw
int scandir(const char *dir, struct dirent ***namelist,
int (*select)(const struct dirent *),
int (*compar)(const struct dirent **, const struct dirent **)) {
DIR *d;
struct dirent *entry;
register int i=0;
size_t entrysize;
if ((d=opendir(dir)) == NULL)
return(-1);
*namelist=NULL;
while ((entry=readdir(d)) != NULL)
{
if (select == NULL || (select != NULL && (*select)(entry)))
{
*namelist=(struct dirent **)realloc((void *)(*namelist),
(size_t)((i+1)*sizeof(struct dirent *)));
if (*namelist == NULL) return(-1);
entrysize=sizeof(struct dirent)-sizeof(entry->d_name)+strlen(entry->d_name)+1;
(*namelist)[i]=(struct dirent *)malloc(entrysize);
if ((*namelist)[i] == NULL) return(-1);
memcpy((*namelist)[i], entry, entrysize);
i++;
}
}
if (closedir(d)) return(-1);
if (i == 0) return(-1);
if (compar != NULL)
qsort((void *)(*namelist), (size_t)i, sizeof(struct dirent *), compar);
return(i);
}
int alphasort(const struct dirent **a, const struct dirent **b) {
return(strcmpi((*a)->d_name, (*b)->d_name));
}
Last edited by qbism on Tue Jan 24, 2012 12:12 am, edited 1 time in total.
-
qbism - Posts: 1236
- Joined: Thu Nov 04, 2004 5:51 am
Re: Simple Cusom Maplist
I compiled it under linux too but it gave same errors. Can please someone take a look at the menu.c I posted and tell me if I committed some error?
@qbism: the part of code you write: where should I put it?
Thanks
@qbism: the part of code you write: where should I put it?
Thanks
Meadow Fun!! - my first commercial game, made with FTEQW game engine
- toneddu2000
- Posts: 1352
- Joined: Tue Feb 24, 2009 4:39 pm
- Location: Italy
Re: Simple Cusom Maplist
Put it in menu.c, above void SetSavename () and under #include<dirent.h>
Don't do the other stuff you tried.
Some systems are #include <sys/dirent.h>
Don't do the other stuff you tried.
Some systems are #include <sys/dirent.h>
-
qbism - Posts: 1236
- Joined: Thu Nov 04, 2004 5:51 am
Re: Simple Cusom Maplist
edited alphasort in snippit above, return strcmpi (case insensitive) rather than strcmp
-
qbism - Posts: 1236
- Joined: Thu Nov 04, 2004 5:51 am
Re: Simple Cusom Maplist
I thing MSVC dont handle the crosscompiler. cygwin or mingw can use the same libs and aso the include fieles mingw i a bit faster then cygwin but i perfer it its easy to handle and i use it for wii, gamecube etc too
I am sorry for my English...
-

Rikku2000 - Posts: 49
- Joined: Wed Oct 20, 2010 6:33 pm
- Location: Germany
8 posts
• Page 1 of 1
Return to Programming Tutorials
Who is online
Users browsing this forum: No registered users and 1 guest