diff options
34 files changed, 419 insertions, 163 deletions
diff --git a/data/skins/bluekitty.png b/data/skins/bluekitty.png new file mode 100644 index 00000000..dbb4d508 --- /dev/null +++ b/data/skins/bluekitty.png Binary files differdiff --git a/data/skins/bluestripe.png b/data/skins/bluestripe.png new file mode 100644 index 00000000..3ccc2236 --- /dev/null +++ b/data/skins/bluestripe.png Binary files differdiff --git a/data/skins/brownbear.png b/data/skins/brownbear.png new file mode 100644 index 00000000..89811708 --- /dev/null +++ b/data/skins/brownbear.png Binary files differdiff --git a/data/skins/cammo.png b/data/skins/cammo.png new file mode 100644 index 00000000..83b4a795 --- /dev/null +++ b/data/skins/cammo.png Binary files differdiff --git a/data/skins/cammostripes.png b/data/skins/cammostripes.png new file mode 100644 index 00000000..3e2cd147 --- /dev/null +++ b/data/skins/cammostripes.png Binary files differdiff --git a/data/skins/coala.png b/data/skins/coala.png new file mode 100644 index 00000000..d4fe0e2a --- /dev/null +++ b/data/skins/coala.png Binary files differdiff --git a/data/skins/limekitty.png b/data/skins/limekitty.png new file mode 100644 index 00000000..3c69bd14 --- /dev/null +++ b/data/skins/limekitty.png Binary files differdiff --git a/data/skins/ninja.png b/data/skins/ninja.png new file mode 100644 index 00000000..f904dfa8 --- /dev/null +++ b/data/skins/ninja.png Binary files differdiff --git a/data/skins/pinky.png b/data/skins/pinky.png new file mode 100644 index 00000000..2308c4b4 --- /dev/null +++ b/data/skins/pinky.png Binary files differdiff --git a/data/skins/redbopp.png b/data/skins/redbopp.png new file mode 100644 index 00000000..0432b65f --- /dev/null +++ b/data/skins/redbopp.png Binary files differdiff --git a/data/skins/redstripe.png b/data/skins/redstripe.png new file mode 100644 index 00000000..6cbbef0f --- /dev/null +++ b/data/skins/redstripe.png Binary files differdiff --git a/data/skins/saddo.png b/data/skins/saddo.png new file mode 100644 index 00000000..8fb744e6 --- /dev/null +++ b/data/skins/saddo.png Binary files differdiff --git a/data/skins/toptri.png b/data/skins/toptri.png new file mode 100644 index 00000000..3849e01f --- /dev/null +++ b/data/skins/toptri.png Binary files differdiff --git a/data/skins/twinbop.png b/data/skins/twinbop.png new file mode 100644 index 00000000..fae16cb0 --- /dev/null +++ b/data/skins/twinbop.png Binary files differdiff --git a/data/skins/twintri.png b/data/skins/twintri.png new file mode 100644 index 00000000..a12bfb0c --- /dev/null +++ b/data/skins/twintri.png Binary files differdiff --git a/data/skins/warpaint.png b/data/skins/warpaint.png new file mode 100644 index 00000000..aa9142c5 --- /dev/null +++ b/data/skins/warpaint.png Binary files differdiff --git a/datasrc/teewars.ds b/datasrc/teewars.ds index 0b681897..2a28d89e 100644 --- a/datasrc/teewars.ds +++ b/datasrc/teewars.ds @@ -618,19 +618,20 @@ sprites { } - tees images.char_default 16 64 { - tee_body 0 0 4 4 - tee_body_outline 4 0 4 4 - tee_foot 8 3 2 1 - tee_foot_outline 13 2 2 1 - tee_hand 8 0 2 2 - tee_hand_outline 13 0 2 2 + tees images.char_default 8 4 { + tee_body 0 0 3 3 + tee_body_outline 3 0 3 3 + tee_foot 6 1 2 1 + tee_foot_outline 6 2 2 1 + tee_hand 6 0 1 1 + tee_hand_outline 7 0 1 1 - tee_eye_normal 10 2 1 1 - tee_eye_pain 11 3 1 1 - tee_eye_happy 11 2 1 1 - tee_eye_surprise 12 0 1 1 - tee_eye_angry 10 3 1 1 + tee_eye_normal 2 3 1 1 + tee_eye_angry 3 3 1 1 + tee_eye_pain 4 3 1 1 + tee_eye_happy 5 3 1 1 + tee_eye_dead 6 3 1 1 + tee_eye_surprise 7 3 1 1 } chatbubbles images.chat_bubbles 4 4 { diff --git a/src/engine/client/client.c b/src/engine/client/client.c index 9445e6d7..df53d142 100644 --- a/src/engine/client/client.c +++ b/src/engine/client/client.c @@ -19,7 +19,7 @@ #include <mastersrv/mastersrv.h> -const int prediction_margin = 5; /* magic network prediction value */ +const int prediction_margin = 10; /* magic network prediction value */ /* Server Time @@ -182,6 +182,7 @@ SMOOTHTIME game_time; SMOOTHTIME predicted_time; GRAPH intra_graph; +GRAPH predict_graph; /* --- input snapping --- */ static int input_data[MAX_INPUT_SIZE] = {0}; @@ -272,11 +273,11 @@ static void client_send_info() msg_pack_string(config.player_name, 128); msg_pack_string(config.clan_name, 128); msg_pack_string(config.password, 128); - msg_pack_string("myskin", 128); msg_pack_end(); client_send_msg(); } + static void client_send_entergame() { msg_pack_start_system(NETMSG_ENTERGAME, MSGFLAG_VITAL); @@ -284,6 +285,13 @@ static void client_send_entergame() client_send_msg(); } +static void client_send_ready() +{ + msg_pack_start_system(NETMSG_READY, MSGFLAG_VITAL); + msg_pack_end(); + client_send_msg(); +} + static void client_send_error(const char *error) { /* @@ -380,6 +388,14 @@ static void client_on_enter_game() current_recv_tick = 0; } +void client_entergame() +{ + /* now we will wait for two snapshots */ + /* to finish the connection */ + client_send_entergame(); + client_on_enter_game(); +} + void client_connect(const char *server_address_str) { char buf[512]; @@ -412,6 +428,8 @@ void client_connect(const char *server_address_str) graph_init(&intra_graph, 0.0f, 1.0f); graph_init(&input_late_graph, 0.0f, 1.0f); + graph_init(&predict_graph, 0.0f, 200.0f); + } void client_disconnect() @@ -463,8 +481,9 @@ static void client_debug_render() /* render graphs */ gfx_mapscreen(0,0,400.0f,300.0f); - graph_render(&game_time.graph, 300, 10, 90, 50); + graph_render(&predict_graph, 300, 10, 90, 50); graph_render(&predicted_time.graph, 300, 10+50+10, 90, 50); + graph_render(&intra_graph, 300, 10+50+10+50+10, 90, 50); graph_render(&input_late_graph, 300, 10+50+10+50+10+50+10, 90, 50); @@ -574,13 +593,15 @@ static void client_process_packet(NETPACKET *packet) if(map_load(map)) { - modc_entergame(); - client_send_entergame(); dbg_msg("client/network", "loading done"); - /* now we will wait for two snapshots */ - /* to finish the connection */ + client_send_ready(); + modc_connected(); - client_on_enter_game(); + /* + modc_entergame(); + client_send_entergame(); + */ + /*client_on_enter_game();*/ } else { @@ -736,7 +757,7 @@ static void client_process_packet(NETPACKET *packet) if(recived_snapshots == 2) { /* start at 200ms and work from there */ - st_init(&predicted_time, (game_tick+10)*time_freq()/50); + st_init(&predicted_time, game_tick*time_freq()/50); st_init(&game_time, (game_tick-1)*time_freq()/50); snapshots[SNAP_PREV] = snapshot_storage.first; snapshots[SNAP_CURRENT] = snapshot_storage.last; @@ -744,6 +765,11 @@ static void client_process_packet(NETPACKET *packet) client_set_state(CLIENTSTATE_ONLINE); } + { + int64 now = time_get(); + graph_add(&predict_graph, (st_get(&predicted_time, now)-st_get(&game_time, now))/(float)time_freq()); + } + st_update(&game_time, (game_tick-1)*time_freq()/50); /* ack snapshot */ @@ -950,15 +976,16 @@ static void client_run(const char *direct_connect_server) if(inp_key_pressed(KEY_F2)) inp_mouse_mode_relative(); - if(inp_key_pressed(KEY_LCTRL) && inp_key_pressed('Q')) - break; - if(inp_key_pressed(KEY_F5)) { ack_game_tick = -1; client_send_input(); } } + + /* panic quit button */ + if(inp_key_pressed(KEY_LCTRL) && inp_key_pressed(KEY_LSHIFT) && inp_key_pressed('Q')) + break; /* pump the network */ client_pump_network(); diff --git a/src/engine/client/gfx.c b/src/engine/client/gfx.c index 3bf8cfe4..31a87611 100644 --- a/src/engine/client/gfx.c +++ b/src/engine/client/gfx.c @@ -536,8 +536,10 @@ void gfx_swap() for(; index < 1000; index++) { - IOHANDLE io = io_open(filename, IOFLAG_READ); + IOHANDLE io; sprintf(filename, "screenshot%04d.png", index); + io = io_open(filename, IOFLAG_READ); + if(io) io_close(io); else diff --git a/src/engine/config_variables.h b/src/engine/config_variables.h index 4ef8958e..f3820901 100644 --- a/src/engine/config_variables.h +++ b/src/engine/config_variables.h @@ -2,7 +2,9 @@ MACRO_CONFIG_INT(volume, 200, 0, 255) MACRO_CONFIG_INT(cpu_throttle, 0, 0, 1) + MACRO_CONFIG_STR(player_name, 32, "nameless tee") + MACRO_CONFIG_STR(clan_name, 32, "") MACRO_CONFIG_STR(password, 32, "") diff --git a/src/engine/interface.h b/src/engine/interface.h index c57c170d..0eaabc20 100644 --- a/src/engine/interface.h +++ b/src/engine/interface.h @@ -743,9 +743,12 @@ int modmenu_render(int ingame); /* undocumented callbacks */ +void modc_connected(); void modc_message(int msg); void modc_predict(); + void mods_message(int msg, int client_id); +void mods_connected(int client_id); const char *modc_net_version(); @@ -753,6 +756,9 @@ const char *mods_net_version(); /* server */ int server_getclientinfo(int client_id, CLIENT_INFO *info); +const char *server_clientname(int client_id); +void server_setclientname(int client_id, const char *name); + int server_tick(); int server_tickspeed(); @@ -823,6 +829,7 @@ int *client_get_input(int tick); void client_connect(const char *address); void client_disconnect(); void client_quit(); +void client_entergame(); void client_rcon(const char *cmd); diff --git a/src/engine/protocol.h b/src/engine/protocol.h index 96ad1e6b..822a735f 100644 --- a/src/engine/protocol.h +++ b/src/engine/protocol.h @@ -1,5 +1,28 @@ #include "system.h" +/* + Connection diagram - How the initilization works. + + Client -> INFO -> Server + Contains version info, name, and some other info. + + Client <- MAP <- Server + Contains current map. + + Client -> READY -> Server + The client has loaded the map and is ready to go, + but the mod needs to send it's information aswell. + modc_connected is called on the client and + mods_connected is called on the server. + The client should call client_entergame when the + mod has done it's initilization. + + Client -> ENTERGAME -> Server + Tells the server to start sending snapshots. + client_entergame and server_client_enter is called. +*/ + + enum { NETMSG_NULL=0, @@ -15,6 +38,7 @@ enum NETMSG_SNAPSMALL, /* sent by client */ + NETMSG_READY, NETMSG_ENTERGAME, NETMSG_INPUT, NETMSG_CMD, diff --git a/src/engine/server/server.c b/src/engine/server/server.c index 8fa10d7b..b1bf5e4d 100644 --- a/src/engine/server/server.c +++ b/src/engine/server/server.c @@ -57,8 +57,9 @@ static int snap_id_inited = 0; enum { SRVCLIENT_STATE_EMPTY = 0, - SRVCLIENT_STATE_CONNECTING = 1, - SRVCLIENT_STATE_INGAME = 2 + SRVCLIENT_STATE_CONNECTING, + SRVCLIENT_STATE_READY, + SRVCLIENT_STATE_INGAME }; typedef struct @@ -161,6 +162,20 @@ void snap_free_id(int id) } } +const char *server_clientname(int client_id) +{ + if(client_id < 0 || client_id > MAX_CLIENTS || clients[client_id].state < SRVCLIENT_STATE_READY) + return "(invalid client)"; + return clients[client_id].name; +} + +void server_setclientname(int client_id, const char *name) +{ + if(client_id < 0 || client_id > MAX_CLIENTS || clients[client_id].state < SRVCLIENT_STATE_READY) + return; + strncpy(clients[client_id].name, name, MAX_NAME_LENGTH); +} + int server_tick() { return current_tick; @@ -404,7 +419,6 @@ static void server_process_client_packet(NETPACKET *packet) { char version[64]; const char *password; - const char *skin; strncpy(version, msg_unpack_string(), 64); if(strcmp(version, mods_net_version()) != 0) { @@ -418,9 +432,6 @@ static void server_process_client_packet(NETPACKET *packet) strncpy(clients[cid].name, msg_unpack_string(), MAX_NAME_LENGTH); strncpy(clients[cid].clan, msg_unpack_string(), MAX_CLANNAME_LENGTH); password = msg_unpack_string(); - skin = msg_unpack_string(); - (void)password; /* ignore these variables */ - (void)skin; if(config.password[0] != 0 && strcmp(config.password, password) != 0) { @@ -431,6 +442,15 @@ static void server_process_client_packet(NETPACKET *packet) server_send_map(cid); } + else if(msg == NETMSG_READY) + { + if(clients[cid].state == SRVCLIENT_STATE_CONNECTING) + { + dbg_msg("server", "player is ready. cid=%x", cid); + clients[cid].state = SRVCLIENT_STATE_READY; + mods_connected(cid); + } + } else if(msg == NETMSG_ENTERGAME) { if(clients[cid].state != SRVCLIENT_STATE_INGAME) diff --git a/src/game/client/game_client.cpp b/src/game/client/game_client.cpp index 471cb604..e966287e 100644 --- a/src/game/client/game_client.cpp +++ b/src/game/client/game_client.cpp @@ -26,10 +26,8 @@ enum data_container *data = 0x0; -static int charids[16] = {2,10,0,4,12,6,9,1,3,15,13,11,7,5,8,14}; - int gametype = GAMETYPE_DM; -static int skinseed = 0; +//static int skinseed = 0; static int music_menu = -1; static int music_menu_id = -1; @@ -53,13 +51,42 @@ static const obj_player_character *local_prev_character = 0; static const obj_player_info *local_info = 0; static const obj_game *gameobj = 0; -struct client_data +// do this better and nicer +struct skin +{ + int org_texture; + int color_texture; + char name[31]; + const char term[1]; +}; + +enum +{ + MAX_SKINS=256, +}; + +struct tee_render_info +{ + int texture; + vec4 color; +}; + +static skin skins[MAX_SKINS] = {{-1, -1, {0}, {0}}}; +static int num_skins = 0; + +static struct client_data { char name[64]; + char skin_name[64]; + int skin_id; + int skin_color; int team; int emoticon; int emoticon_start; player_core predicted; + + tee_render_info skin_info; + } client_datas[MAX_CLIENTS]; class client_effects @@ -514,6 +541,46 @@ static void render_loading(float percent) gfx_swap(); } +static void skinscan(const char *name, int is_dir, void *user) +{ + int l = strlen(name); + if(l < 4 || is_dir || num_skins == MAX_SKINS) + return; + if(strcmp(name+l-4, ".png") != 0) + return; + + char buf[512]; + sprintf(buf, "data/skins/%s", name); + IMAGE_INFO info; + if(!gfx_load_png(&info, buf)) + { + dbg_msg("game", "failed to load skin from %s", name); + return; + } + + skins[num_skins].org_texture = gfx_load_texture_raw(info.width, info.height, info.format, info.data); + + // create colorless version + unsigned char *d = (unsigned char *)info.data; + int step = info.format == IMG_RGBA ? 4 : 3; + + for(int i = 0; i < info.width*info.height; i++) + { + int v = (d[i*step]+d[i*step+1]+d[i*step+2])/3; + d[i*step] = v; + d[i*step+1] = v; + d[i*step+2] = v; + } + + skins[num_skins].color_texture = gfx_load_texture_raw(info.width, info.height, info.format, info.data); + mem_free(info.data); + + // set skin data + strncpy(skins[num_skins].name, name, min((int)sizeof(skins[num_skins].name),l-4)); + dbg_msg("game", "load skin %s", skins[num_skins].name); + num_skins++; +} + extern "C" void modc_init() { // setup sound channels @@ -556,27 +623,13 @@ extern "C" void modc_init() data->images[i].id = gfx_load_texture(data->images[i].filename); current++; } + + // load skins + fs_listdir("data/skins", skinscan, 0); } extern "C" void modc_entergame() { - col_init(32); - img_init(); - tilemap_init(); - chat_reset(); - - proj_particles.reset(); - - for(int i = 0; i < MAX_CLIENTS; i++) - { - client_datas[i].name[0] = 0; - client_datas[i].team = 0; - client_datas[i].emoticon = 0; - client_datas[i].emoticon_start = -1; - } - - for(int i = 0; i < killmsg_max; i++) - killmsgs[i].tick = -100000; } extern "C" void modc_shutdown() @@ -755,6 +808,10 @@ extern "C" void modc_predict() // predict for(int tick = client_tick()+1; tick <= client_predtick(); tick++) { + // fetch the local + if(tick == client_predtick() && world.players[local_cid]) + predicted_prev_player = *world.players[local_cid]; + // first calculate where everyone should move for(int c = 0; c < MAX_CLIENTS; c++) { @@ -781,16 +838,10 @@ extern "C" void modc_predict() world.players[c]->move(); world.players[c]->quantize(); - - // get the data from the local player - if(local_cid == c && world.players[local_cid]) - { - if(tick == client_predtick()) - predicted_player = *world.players[local_cid]; - else if(tick == client_predtick()-1) - predicted_prev_player = *world.players[local_cid]; - } } + + if(tick == client_predtick() && world.players[local_cid]) + predicted_player = *world.players[local_cid]; } } @@ -850,10 +901,15 @@ extern "C" void modc_newsnapshot() } } -void send_changename_request(const char *name) +void send_info(bool start) { - msg_pack_start(MSG_CHANGENAME, MSGFLAG_VITAL); - msg_pack_string(name, 64); + if(start) + msg_pack_start(MSG_STARTINFO, MSGFLAG_VITAL); + else + msg_pack_start(MSG_CHANGEINFO, MSGFLAG_VITAL); + msg_pack_string(config.player_name, 64); + msg_pack_string(config.player_skin, 64); + msg_pack_int(config.player_color); msg_pack_end(); client_send_msg(); } @@ -1043,10 +1099,11 @@ static void anim_eval_add(animstate *state, animation *anim, float time, float a anim_add(state, &add, amount); } -static void render_hand(int skin, vec2 center_pos, vec2 dir, float angle_offset, vec2 post_rot_offset) +static void render_hand(int skin_id, vec2 center_pos, vec2 dir, float angle_offset, vec2 post_rot_offset) { // for drawing hand - int shift = charids[skin%16]; + skin_id = skin_id%num_skins; + float basesize = 10.0f; //dir = normalize(hook_pos-pos); @@ -1066,7 +1123,8 @@ static void render_hand(int skin, vec2 center_pos, vec2 dir, float angle_offset, hand_pos += dirx * post_rot_offset.x; hand_pos += diry * post_rot_offset.y; - gfx_texture_set(data->images[IMAGE_CHAR_DEFAULT].id); + //gfx_texture_set(data->images[IMAGE_CHAR_DEFAULT].id); + gfx_texture_set(skins[skin_id].color_texture); gfx_quads_begin(); // two passes @@ -1074,7 +1132,7 @@ static void render_hand(int skin, vec2 center_pos, vec2 dir, float angle_offset, { bool outline = i == 0; - select_sprite(outline?SPRITE_TEE_HAND_OUTLINE:SPRITE_TEE_HAND, 0, 0, shift*4); + select_sprite(outline?SPRITE_TEE_HAND_OUTLINE:SPRITE_TEE_HAND, 0, 0, 0); gfx_quads_setrotation(angle); gfx_quads_draw(hand_pos.x, hand_pos.y, 2*basesize, 2*basesize); } @@ -1083,30 +1141,33 @@ static void render_hand(int skin, vec2 center_pos, vec2 dir, float angle_offset, gfx_quads_end(); } -static void render_tee(animstate *anim, int skin, int emote, vec2 dir, vec2 pos) +static void render_tee(animstate *anim, tee_render_info *info, int emote, vec2 dir, vec2 pos) { - vec2 direction = dir; + vec2 direction = dir; vec2 position = pos; - gfx_texture_set(data->images[IMAGE_CHAR_DEFAULT].id); + //gfx_texture_set(data->images[IMAGE_CHAR_DEFAULT].id); + gfx_texture_set(info->texture); gfx_quads_begin(); + gfx_setcolor(info->color.r, info->color.g, info->color.b, info->color.a); + //gfx_quads_draw(pos.x, pos.y-128, 128, 128); - // draw foots + // first pass we draw the outline + // second pass we draw the filling for(int p = 0; p < 2; p++) { - // first pass we draw the outline - // second pass we draw the filling int outline = p==0 ? 1 : 0; - int shift = skin; + //int shift = skin; for(int f = 0; f < 2; f++) { - float basesize = 10.0f; + float basesize = 16.0f; if(f == 1) { gfx_quads_setrotation(anim->body.angle*pi*2); + // draw body - select_sprite(outline?SPRITE_TEE_BODY_OUTLINE:SPRITE_TEE_BODY, 0, 0, shift*4); + select_sprite(outline?SPRITE_TEE_BODY_OUTLINE:SPRITE_TEE_BODY, 0, 0, 0); gfx_quads_draw(position.x+anim->body.x, position.y+anim->body.y, 4*basesize, 4*basesize); // draw eyes @@ -1115,34 +1176,34 @@ static void render_tee(animstate *anim, int skin, int emote, vec2 dir, vec2 pos) switch (emote) { case EMOTE_PAIN: - select_sprite(SPRITE_TEE_EYE_PAIN, 0, 0, shift*4); + select_sprite(SPRITE_TEE_EYE_PAIN, 0, 0, 0); break; case EMOTE_HAPPY: - select_sprite(SPRITE_TEE_EYE_HAPPY, 0, 0, shift*4); + select_sprite(SPRITE_TEE_EYE_HAPPY, 0, 0, 0); break; case EMOTE_SURPRISE: - select_sprite(SPRITE_TEE_EYE_SURPRISE, 0, 0, shift*4); + select_sprite(SPRITE_TEE_EYE_SURPRISE, 0, 0, 0); break; case EMOTE_ANGRY: - select_sprite(SPRITE_TEE_EYE_ANGRY, 0, 0, shift*4); + select_sprite(SPRITE_TEE_EYE_ANGRY, 0, 0, 0); break; default: - select_sprite(SPRITE_TEE_EYE_NORMAL, 0, 0, shift*4); + select_sprite(SPRITE_TEE_EYE_NORMAL, 0, 0, 0); break; } int h = emote == EMOTE_BLINK ? (int)(basesize/3) : (int)(basesize); - gfx_quads_draw(position.x-4+direction.x*4, position.y-8+direction.y*3, basesize, h); - gfx_quads_draw(position.x+4+direction.x*4, position.y-8+direction.y*3, -basesize, h); + gfx_quads_draw(position.x-4+direction.x*4, position.y-8+direction.y*3, basesize*1.5f, h*1.5f); + gfx_quads_draw(position.x+4+direction.x*4, position.y-8+direction.y*3, -basesize*1.5f, h*1.5f); } } // draw feet - select_sprite(outline?SPRITE_TEE_FOOT_OUTLINE:SPRITE_TEE_FOOT, 0, 0, shift*4); + select_sprite(outline?SPRITE_TEE_FOOT_OUTLINE:SPRITE_TEE_FOOT, 0, 0, 0); keyframe *foot = f ? &anim->front_foot : &anim->back_foot; - float w = basesize*2.5f; - float h = basesize*1.425f; + float w = basesize*2.5f*1.5f; + float h = basesize*1.425f*1.5f; gfx_quads_setrotation(foot->angle*pi*2); gfx_quads_draw(position.x+foot->x, position.y+foot->y, w, h); @@ -1249,10 +1310,10 @@ static void render_player( intratick = client_intrapredtick(); } - int skin = charids[info.clientid]; - - if(gametype != GAMETYPE_DM) - skin = info.team*9; // 0 or 9 + // TODO: proper skin selection + int skin_id = client_datas[info.clientid].skin_id; //charids[info.clientid]; + //if(gametype != GAMETYPE_DM) + //skin_id = info.team*9; // 0 or 9 vec2 direction = get_direction(player.angle); float angle = player.angle/256.0f; @@ -1317,7 +1378,7 @@ static void render_player( gfx_quads_setrotation(0); gfx_quads_end(); - render_hand(skin, position, normalize(hook_pos-pos), -pi/2, vec2(20, 0)); + render_hand(skin_id, position, normalize(hook_pos-pos), -pi/2, vec2(20, 0)); } // draw gun @@ -1437,9 +1498,9 @@ static void render_player( switch (player.weapon) { - case WEAPON_GUN: render_hand(skin, p, direction, -3*pi/4, vec2(-15, 4)); break; - case WEAPON_SHOTGUN: render_hand(skin, p, direction, -pi/2, vec2(-5, 4)); break; - case WEAPON_ROCKET: render_hand(skin, p, direction, -pi/2, vec2(-4, 7)); break; + case WEAPON_GUN: render_hand(skin_id, p, direction, -3*pi/4, vec2(-15, 4)); break; + case WEAPON_SHOTGUN: render_hand(skin_id, p, direction, -pi/2, vec2(-5, 4)); break; + case WEAPON_ROCKET: render_hand(skin_id, p, direction, -pi/2, vec2(-4, 7)); break; } } @@ -1448,11 +1509,13 @@ static void render_player( if(info.local && config.debug) { vec2 ghost_position = mix(vec2(prev_char->x, prev_char->y), vec2(player_char->x, player_char->y), client_intratick()); - render_tee(&state, 15, player.emote, direction, ghost_position); // render ghost + tee_render_info ghost = client_datas[info.clientid].skin_info; + ghost.color.a = 0.5f; + render_tee(&state, &ghost, player.emote, direction, ghost_position); // render ghost } // render the tee - render_tee(&state, skin, player.emote, direction, position); + render_tee(&state, &client_datas[info.clientid].skin_info, player.emote, direction, position); if(player.state == STATE_CHATTING) { @@ -1785,7 +1848,7 @@ void render_scoreboard(float x, float y, float w, int team, const char *title) gfx_pretty_text(x+w-tw-35, y, font_size, buf, -1); // render avatar - render_tee(&idlestate, info->clientid, EMOTE_NORMAL, vec2(1,0), vec2(x+90, y+28)); + render_tee(&idlestate, &client_datas[info->clientid].skin_info, EMOTE_NORMAL, vec2(1,0), vec2(x+90, y+28)); y += 50.0f; } } @@ -1882,7 +1945,7 @@ void render_world(float center_x, float center_y, float zoom) const void *info = snap_find_item(SNAP_CURRENT, OBJTYPE_PLAYER_INFO, item.id); if(prev && prev_info && info) { - client_datas[((const obj_player_info *)data)->clientid].team = ((const obj_player_info *)data)->team; + client_datas[((const obj_player_info *)info)->clientid].team = ((const obj_player_info *)info)->team; render_player( (const obj_player_character *)prev, (const obj_player_character *)data, @@ -1905,6 +1968,22 @@ void render_world(float center_x, float center_y, float zoom) damageind.render(); } +static void next_skin() +{ + int skin_id = 0; + for(int i = 0; i < num_skins; i++) + { + if(strcmp(config.player_skin, skins[i].name) == 0) + { + skin_id = (i+1)%num_skins; + break; + } + } + + config_set_player_skin(&config, skins[skin_id].name); + send_info(false); +} + static void do_input(int *v, int key) { *v += inp_key_presses(key) + inp_key_releases(key); @@ -1915,6 +1994,9 @@ static void do_input(int *v, int key) void render_game() { + if(inp_key_down('L')) + next_skin(); + float width = 400*3.0f; float height = 300*3.0f; @@ -2319,8 +2401,8 @@ void render_game() // render victim tee x -= 24.0f; - int skin = gametype == GAMETYPE_TDM ? skinseed + client_datas[killmsgs[r].victim].team : killmsgs[r].victim; - render_tee(&idlestate, skin, EMOTE_PAIN, vec2(-1,0), vec2(x, y+28)); + //int skin = gametype == GAMETYPE_TDM ? skinseed + client_datas[killmsgs[r].victim].team : killmsgs[r].victim; + render_tee(&idlestate, &client_datas[killmsgs[r].victim].skin_info, EMOTE_PAIN, vec2(-1,0), vec2(x, y+28)); x -= 32.0f; // render weapon @@ -2337,8 +2419,8 @@ void render_game() // render killer tee x -= 24.0f; - skin = gametype == GAMETYPE_TDM ? skinseed + client_datas[killmsgs[r].killer].team : killmsgs[r].killer; - render_tee(&idlestate, skin, EMOTE_ANGRY, vec2(1,0), vec2(x, y+28)); + //skin = gametype == GAMETYPE_TDM ? skinseed + client_datas[killmsgs[r].killer].team : killmsgs[r].killer; + render_tee(&idlestate, &client_datas[killmsgs[r].killer].skin_info, EMOTE_ANGRY, vec2(1,0), vec2(x, y+28)); x -= 32.0f; // render killer name @@ -2532,6 +2614,7 @@ extern "C" void modc_render() render_game(); // handle team switching + // TODO: FUGLY!!! if(config.team != -10) { msg_pack_start(MSG_SETTEAM, MSGFLAG_VITAL); @@ -2586,11 +2669,33 @@ extern "C" void modc_message(int msg) else snd_play(CHN_GUI, data->sounds[SOUND_CHAT_SERVER].sounds[0].id, 0); } - else if(msg == MSG_SETNAME) + else if(msg == MSG_SETINFO) { int cid = msg_unpack_int(); const char *name = msg_unpack_string(); + const char *skinname = msg_unpack_string(); + int color = msg_unpack_int(); + (void)color; strncpy(client_datas[cid].name, name, 64); + strncpy(client_datas[cid].skin_name, skinname, 64); + client_datas[cid].skin_info.color = vec4(1,1,1,1); //color; + + // find new skin + client_datas[cid].skin_id = 0; + for(int i = 0; i < num_skins; i++) + { + if(strcmp(skins[i].name, client_datas[cid].skin_name) == 0) + { + client_datas[cid].skin_id = i; + break; + } + } + + client_datas[cid].skin_info.texture = skins[client_datas[cid].skin_id].org_texture; + } + else if(msg == MSG_READY_TO_ENTER) + { + client_entergame(); } else if(msg == MSG_KILLMSG) { @@ -2609,5 +2714,28 @@ extern "C" void modc_message(int msg) } } +extern "C" void modc_connected() +{ + // init some stuff + col_init(32); + img_init(); + tilemap_init(); + chat_reset(); + + proj_particles.reset(); + + for(int i = 0; i < MAX_CLIENTS; i++) + { + client_datas[i].name[0] = 0; + client_datas[i].team = 0; + client_datas[i].emoticon = 0; + client_datas[i].emoticon_start = -1; + } + + for(int i = 0; i < killmsg_max; i++) + killmsgs[i].tick = -100000; + + send_info(true); +} extern "C" const char *modc_net_version() { return TEEWARS_NETVERSION; } diff --git a/src/game/client/menu.cpp b/src/game/client/menu.cpp index 48f7147c..afcb1cfe 100644 --- a/src/game/client/menu.cpp +++ b/src/game/client/menu.cpp @@ -1303,7 +1303,7 @@ static int settings_sound_render() } extern void draw_round_rect(float x, float y, float w, float h, float r); -void send_changename_request(const char *name); +extern void send_info(bool); static int settings_render(bool ingame) { @@ -1344,10 +1344,13 @@ static int settings_render(bool ingame) if (ui_do_button(&save_button, "Save", 0, 482, 490, 128, 48, draw_teewars_button, 0)) { // did we change our name? - if (ingame && strcmp(config.player_name, config_copy.player_name) != 0) - send_changename_request(config_copy.player_name); + bool name_changed = strcmp(config.player_name, config_copy.player_name) != 0; config = config_copy; + + if (ingame && name_changed) + send_info(false); + #ifdef CONF_PLATFORM_MACOSX config_save("~/.teewars"); #else diff --git a/src/game/game_protocol.h b/src/game/game_protocol.h index 6be89e35..982a14b2 100644 --- a/src/game/game_protocol.h +++ b/src/game/game_protocol.h @@ -38,15 +38,17 @@ enum enum { MSG_NULL=0, - MSG_SAY, - MSG_CHAT, - MSG_SETNAME, - MSG_KILLMSG, + MSG_SAY, // client -> server + MSG_CHAT, // server -> client + MSG_SETINFO, // server -> client - contains name, skin and color info + MSG_KILLMSG, // server -> client MSG_SETTEAM, MSG_JOIN, MSG_QUIT, MSG_EMOTICON, - MSG_CHANGENAME, + MSG_STARTINFO, // client -> server + MSG_CHANGEINFO, // client -> server + MSG_READY_TO_ENTER // server -> client }; enum diff --git a/src/game/game_variables.h b/src/game/game_variables.h index 352675ba..32e277f1 100644 --- a/src/game/game_variables.h +++ b/src/game/game_variables.h @@ -39,6 +39,9 @@ MACRO_CONFIG_INT(dynamic_camera, 1, 0, 1) MACRO_CONFIG_INT(warmup, 0, 0, 0) MACRO_CONFIG_INT(team, -10, -1, 0) +MACRO_CONFIG_INT(player_color, -1, -1, 256) +MACRO_CONFIG_STR(player_skin, 64, "default") + MACRO_CONFIG_INT(dbg_new_gui, 0, 0, 1) diff --git a/src/game/server/game_server.cpp b/src/game/server/game_server.cpp index 8aaa9ab2..f88eefa9 100644 --- a/src/game/server/game_server.cpp +++ b/src/game/server/game_server.cpp @@ -355,11 +355,6 @@ player::player() void player::init() { proximity_radius = phys_size; - name[0] = 'n'; - name[1] = 'o'; - name[2] = 'o'; - name[3] = 'b'; - name[4] = 0; client_id = -1; team = -1; // -1 == spectator extrapowerflags = 0; @@ -406,7 +401,6 @@ void player::set_weapon(int w) active_weapon = w; } - void player::respawn() { spawning = true; @@ -504,9 +498,8 @@ void player::try_respawn() weapons[WEAPON_GUN].got = true; weapons[WEAPON_GUN].ammo = data->weapons[WEAPON_GUN].maxammo; - weapons[WEAPON_SNIPER].got = true; - weapons[WEAPON_SNIPER].ammo = data->weapons[WEAPON_SNIPER].maxammo; - + //weapons[WEAPON_SNIPER].got = true; + //weapons[WEAPON_SNIPER].ammo = data->weapons[WEAPON_SNIPER].maxammo; active_weapon = WEAPON_GUN; last_weapon = WEAPON_HAMMER; @@ -1006,7 +999,9 @@ void player::die(int killer, int weapon) { gameobj->on_player_death(this, get_player(killer), weapon); - dbg_msg("game", "kill killer='%d:%s' victim='%d:%s' weapon=%d", killer, players[killer].name, client_id, name, weapon); + dbg_msg("game", "kill killer='%d:%s' victim='%d:%s' weapon=%d", + killer, server_clientname(killer), + client_id, server_clientname(client_id), weapon); // send the kill message msg_pack_start(MSG_KILLMSG, MSGFLAG_VITAL); @@ -1292,7 +1287,8 @@ void powerup::tick() if(respawntime >= 0) { - dbg_msg("game", "pickup player='%d:%s' item=%d/%d", pplayer->client_id, pplayer->name, type, subtype); + dbg_msg("game", "pickup player='%d:%s' item=%d/%d", + pplayer->client_id, server_clientname(pplayer->client_id), type, subtype); spawntick = server_tick() + server_tickspeed() * respawntime; } } @@ -1448,7 +1444,7 @@ player* intersect_player(vec2 pos0, vec2 pos1, vec2& new_pos, entity* notthis) void send_chat(int cid, int team, const char *msg) { if(cid >= 0 && cid < MAX_CLIENTS) - dbg_msg("chat", "%d:%d:%s: %s", cid, team, players[cid].name, msg); + dbg_msg("chat", "%d:%d:%s: %s", cid, team, server_clientname(cid), msg); else dbg_msg("chat", "*** %s", msg); @@ -1523,17 +1519,15 @@ void mods_client_input(int client_id, void *input) } } -void send_set_name(int cid, const char *old_name, const char *new_name) +void send_info(int who, int to_who) { - msg_pack_start(MSG_SETNAME, MSGFLAG_VITAL); - msg_pack_int(cid); - msg_pack_string(new_name, 64); + msg_pack_start(MSG_SETINFO, MSGFLAG_VITAL); + msg_pack_int(who); + msg_pack_string(server_clientname(who), 64); + msg_pack_string(players[who].skin_name, 64); + msg_pack_int(players[who].skin_color); msg_pack_end(); - server_send_msg(-1); - - char msg[256]; - sprintf(msg, "*** %s changed name to %s", old_name, new_name); - send_chat(-1, -1, msg); + server_send_msg(to_who); } void send_emoticon(int cid, int emoticon) @@ -1547,21 +1541,21 @@ void send_emoticon(int cid, int emoticon) void mods_client_enter(int client_id) { - players[client_id].init(); - players[client_id].client_id = client_id; world->insert_entity(&players[client_id]); players[client_id].respawn(); + dbg_msg("game", "join player='%d:%s'", client_id, server_clientname(client_id)); + + char buf[512]; + sprintf(buf, "%s has joined the game", server_clientname(client_id)); + send_chat(-1, -1, buf); +} - CLIENT_INFO info; // fetch login name - if(server_getclientinfo(client_id, &info)) - { - strcpy(players[client_id].name, info.name); - } - else - strcpy(players[client_id].name, "(bot)"); - +void mods_connected(int client_id) +{ + players[client_id].init(); + players[client_id].client_id = client_id; - dbg_msg("game", "join player='%d:%s'", client_id, players[client_id].name); + //dbg_msg("game", "join player='%d:%s'", client_id, server_clientname(client_id)); // Check which team the player should be on if(gameobj->gametype == GAMETYPE_DM) @@ -1570,9 +1564,10 @@ void mods_client_enter(int client_id) players[client_id].team = gameobj->getteam(client_id); // - msg_pack_start(MSG_SETNAME, MSGFLAG_VITAL); + /* + msg_pack_start(MSG_SETINFO, MSGFLAG_VITAL); msg_pack_int(client_id); - msg_pack_string(players[client_id].name, 64); + msg_pack_string(server_clientname(client_id), 64); msg_pack_end(); server_send_msg(-1); @@ -1580,26 +1575,23 @@ void mods_client_enter(int client_id) { if(players[client_id].client_id != -1) { - msg_pack_start(MSG_SETNAME, MSGFLAG_VITAL); + msg_pack_start(MSG_SETINFO, MSGFLAG_VITAL); msg_pack_int(i); - msg_pack_string(players[i].name, 64); + msg_pack_string(server_clientname(i), 64); msg_pack_end(); server_send_msg(client_id); } - } + }*/ - char buf[512]; - sprintf(buf, "%s has joined the game", players[client_id].name); - send_chat(-1, -1, buf); } void mods_client_drop(int client_id) { char buf[512]; - sprintf(buf, "%s has left the game", players[client_id].name); + sprintf(buf, "%s has left the game", server_clientname(client_id)); send_chat(-1, -1, buf); - dbg_msg("game", "leave player='%d:%s'", client_id, players[client_id].name); + dbg_msg("game", "leave player='%d:%s'", client_id, server_clientname(client_id)); gameobj->on_player_death(&players[client_id], 0, -1); world->remove_entity(&players[client_id]); @@ -1623,18 +1615,50 @@ void mods_message(int msg, int client_id) // Switch team on given client and kill/respawn him players[client_id].set_team(msg_unpack_int()); } - else if (msg == MSG_CHANGENAME) + else if (msg == MSG_CHANGEINFO || msg == MSG_STARTINFO) { const char *name = msg_unpack_string(); + const char *skin_name = msg_unpack_string(); + int skin_color = msg_unpack_int(); // check for invalid chars const char *p = name; while (*p) - if (*p++ < 32) + { + if(*p < 32) return; + p++; + } + - send_set_name(client_id, players[client_id].name, name); - strcpy(players[client_id].name, name); + // + if(msg == MSG_CHANGEINFO && strcmp(name, server_clientname(client_id)) != 0) + { + char msg[256]; + sprintf(msg, "*** %s changed name to %s", server_clientname(client_id), name); + send_chat(-1, -1, msg); + } + + //send_set_name(client_id, players[client_id].name, name); + strncpy(players[client_id].skin_name, skin_name, 64); + server_setclientname(client_id, name); + players[client_id].skin_color = skin_color; + + if(msg == MSG_STARTINFO) + { + // send all info to this client + for(int i = 0; i < MAX_CLIENTS; i++) + { + if(players[i].client_id != -1) + send_info(i, client_id); + } + + msg_pack_start(MSG_READY_TO_ENTER, MSGFLAG_VITAL); + msg_pack_end(); + server_send_msg(client_id); + } + + send_info(client_id, -1); } else if (msg == MSG_EMOTICON) { @@ -1742,8 +1766,9 @@ void mods_init() {*/ for(int i = 0; i < config.dbg_bots ; i++) { + mods_connected(MAX_CLIENTS-i-1); mods_client_enter(MAX_CLIENTS-i-1); - strcpy(players[MAX_CLIENTS-i-1].name, "(bot)"); + //strcpy(players[MAX_CLIENTS-i-1].name, "(bot)"); if(gameobj->gametype != GAMETYPE_DM) players[MAX_CLIENTS-i-1].team = i&1; } diff --git a/src/game/server/srv_common.cpp b/src/game/server/srv_common.cpp index 6d2abf0c..638d31c6 100644 --- a/src/game/server/srv_common.cpp +++ b/src/game/server/srv_common.cpp @@ -28,6 +28,7 @@ gameobject::gameobject() sudden_death = 0; round_start_tick = server_tick(); round_count = 0; + is_teamplay = false; } void gameobject::endround() diff --git a/src/game/server/srv_common.h b/src/game/server/srv_common.h index 1e544753..46c17ed8 100644 --- a/src/game/server/srv_common.h +++ b/src/game/server/srv_common.h @@ -121,6 +121,8 @@ protected: int warmup; int round_count; + bool is_teamplay; + public: int gametype; gameobject(); @@ -237,7 +239,8 @@ public: // int client_id; - char name[64]; + char skin_name[64]; + int skin_color; // input player_input previnput; @@ -287,7 +290,7 @@ public: void respawn(); void set_team(int team); - + bool is_grounded(); void set_weapon(int w); diff --git a/src/game/server/srv_ctf.cpp b/src/game/server/srv_ctf.cpp index 57d81aef..c4cbd574 100644 --- a/src/game/server/srv_ctf.cpp +++ b/src/game/server/srv_ctf.cpp @@ -21,6 +21,8 @@ gameobject_ctf::gameobject_ctf() // report massive failure } } + + is_teamplay = true; } void gameobject_ctf::on_player_spawn(class player *p) diff --git a/src/game/server/srv_tdm.cpp b/src/game/server/srv_tdm.cpp index ba3ff238..c9e4c686 100644 --- a/src/game/server/srv_tdm.cpp +++ b/src/game/server/srv_tdm.cpp @@ -2,6 +2,11 @@ #include "srv_common.h" #include "srv_tdm.h" +gameobject_tdm::gameobject_tdm() +{ + is_teamplay = true; +} + void gameobject_tdm::tick() { if(game_over_tick == -1) diff --git a/src/game/server/srv_tdm.h b/src/game/server/srv_tdm.h index 748c2e9e..5caa00c3 100644 --- a/src/game/server/srv_tdm.h +++ b/src/game/server/srv_tdm.h @@ -2,5 +2,6 @@ class gameobject_tdm : public gameobject { public: + gameobject_tdm(); virtual void tick(); }; diff --git a/src/tools/crapnet.cpp b/src/tools/crapnet.cpp index 842a602d..68e76fa4 100644 --- a/src/tools/crapnet.cpp +++ b/src/tools/crapnet.cpp @@ -97,12 +97,12 @@ int run(int port, NETADDR4 dest) // send and remove packet //if((rand()%20) != 0) // heavy packetloss - // net_udp4_send(socket, &p->send_to, p->data, p->data_size); + net_udp4_send(socket, &p->send_to, p->data, p->data_size); // update lag double flux = rand()/(double)RAND_MAX; int ms_spike = 0; - int ms_flux = 50; + int ms_flux = 20; int ms_ping = 50; current_latency = ((time_freq()*ms_ping)/1000) + (int64)(((time_freq()*ms_flux)/1000)*flux); // 50ms |