From: TimePath Date: Wed, 14 Oct 2015 23:29:49 +0000 (+1100) Subject: Merge branch 'master' into TimePath/guide X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=22692213b5488c88d98734858825b7ddb2b16216;p=xonotic%2Fxonotic-data.pk3dir.git Merge branch 'master' into TimePath/guide # Conflicts: # qcsrc/common/nades.qh # qcsrc/common/vehicles/vehicle.qh # qcsrc/menu/xonotic/dialog_multiplayer_media.qc --- 22692213b5488c88d98734858825b7ddb2b16216 diff --cc qcsrc/common/nades/all.inc index 0000000000,90326ede1f..2c16907240 mode 000000,100644..100644 --- a/qcsrc/common/nades/all.inc +++ b/qcsrc/common/nades/all.inc @@@ -1,0 -1,58 +1,72 @@@ + #define NADE_PROJECTILE(i, projectile, trail) do { \ + this.m_projectile[i] = projectile; \ + this.m_trail[i] = trail; \ + } while (0) + + REGISTER_NADE(NORMAL) { + this.m_color = '1 1 1'; ++#ifndef MENUQC + NADE_PROJECTILE(0, PROJECTILE_NADE, EFFECT_Null); + NADE_PROJECTILE(1, PROJECTILE_NADE_BURN, EFFECT_Null); ++#endif + } + + REGISTER_NADE(NAPALM) { + this.m_color = '2 0.5 0'; + this.m_name = _("Napalm grenade"); + this.m_icon = "nade_napalm"; ++#ifndef MENUQC + NADE_PROJECTILE(0, PROJECTILE_NADE_NAPALM, EFFECT_TR_ROCKET); + NADE_PROJECTILE(1, PROJECTILE_NADE_NAPALM_BURN, EFFECT_SPIDERBOT_ROCKET_TRAIL); ++#endif + } + + REGISTER_NADE(ICE) { + this.m_color = '0 0.5 2'; + this.m_name = _("Ice grenade"); + this.m_icon = "nade_ice"; ++#ifndef MENUQC + NADE_PROJECTILE(0, PROJECTILE_NADE_ICE, EFFECT_TR_NEXUIZPLASMA); + NADE_PROJECTILE(1, PROJECTILE_NADE_ICE_BURN, EFFECT_RACER_ROCKET_TRAIL); ++#endif + } + + REGISTER_NADE(TRANSLOCATE) { + this.m_color = '1 0 1'; + this.m_name = _("Translocate grenade"); + this.m_icon = "nade_translocate"; ++#ifndef MENUQC + NADE_PROJECTILE(0, PROJECTILE_NADE_TRANSLOCATE, EFFECT_TR_CRYLINKPLASMA); + NADE_PROJECTILE(1, PROJECTILE_NADE_TRANSLOCATE, EFFECT_TR_CRYLINKPLASMA); ++#endif + } + + REGISTER_NADE(SPAWN) { + this.m_color = '1 0.9 0'; + this.m_name = _("Spawn grenade"); + this.m_icon = "nade_spawn"; ++#ifndef MENUQC + NADE_PROJECTILE(0, PROJECTILE_NADE_SPAWN, EFFECT_NADE_TRAIL_YELLOW); + NADE_PROJECTILE(1, PROJECTILE_NADE_SPAWN, EFFECT_NADE_TRAIL_YELLOW); ++#endif + } + + REGISTER_NADE(HEAL) { + this.m_color = '1 0 0'; + this.m_name = _("Heal grenade"); + this.m_icon = "nade_heal"; ++#ifndef MENUQC + NADE_PROJECTILE(0, PROJECTILE_NADE_HEAL, EFFECT_NADE_TRAIL_RED); + NADE_PROJECTILE(1, PROJECTILE_NADE_HEAL_BURN, EFFECT_NADE_TRAIL_BURN_RED); ++#endif + } + + REGISTER_NADE(MONSTER) { + this.m_color = '0.25 0.75 0'; + this.m_name = _("Monster grenade"); + this.m_icon = "nade_monster"; ++#ifndef MENUQC + NADE_PROJECTILE(0, PROJECTILE_NADE_MONSTER, EFFECT_NADE_TRAIL_RED); + NADE_PROJECTILE(1, PROJECTILE_NADE_MONSTER_BURN, EFFECT_NADE_TRAIL_BURN_RED); ++#endif + } diff --cc qcsrc/common/nades/all.qh index 0000000000,ad51a1e55e..42d66920a4 mode 000000,100644..100644 --- a/qcsrc/common/nades/all.qh +++ b/qcsrc/common/nades/all.qh @@@ -1,0 -1,82 +1,84 @@@ + #ifndef NADES_ALL_H + #define NADES_ALL_H + + #include "../teams.qh" + + .float healer_lifetime; + .float healer_radius; + + // use slots 70-100 + const int PROJECTILE_NADE = 71; + const int PROJECTILE_NADE_BURN = 72; + const int PROJECTILE_NADE_NAPALM = 73; + const int PROJECTILE_NADE_NAPALM_BURN = 74; + const int PROJECTILE_NAPALM_FOUNTAIN = 75; + const int PROJECTILE_NADE_ICE = 76; + const int PROJECTILE_NADE_ICE_BURN = 77; + const int PROJECTILE_NADE_TRANSLOCATE = 78; + const int PROJECTILE_NADE_SPAWN = 79; + const int PROJECTILE_NADE_HEAL = 80; + const int PROJECTILE_NADE_HEAL_BURN = 81; + const int PROJECTILE_NADE_MONSTER = 82; + const int PROJECTILE_NADE_MONSTER_BURN = 83; + + REGISTRY(Nades, BIT(3)) + REGISTER_REGISTRY(RegisterNades) + #define REGISTER_NADE(id) REGISTER(RegisterNades, NADE_TYPE, Nades, id, m_id, NEW(Nade)) + + CLASS(Nade, Object) + ATTRIB(Nade, m_id, int, 0) + ATTRIB(Nade, m_color, vector, '0 0 0') + ATTRIB(Nade, m_name, string, _("Grenade")) + ATTRIB(Nade, m_icon, string, "nade_normal") + ATTRIBARRAY(Nade, m_projectile, int, 2) + ATTRIBARRAY(Nade, m_trail, entity, 2) + METHOD(Nade, display, void(entity this, void(string name, string icon) returns)) { + returns(this.m_name, sprintf("/gfx/hud/%s/%s", cvar_string("menu_skin"), this.m_icon)); + } + ENDCLASS(Nade) + + REGISTER_NADE(Null); + + #ifdef SVQC + bool healer_send(entity this, entity to, int sf); + #endif + ++#ifndef MENUQC + entity Nade_FromProjectile(float proj) + { + FOREACH(Nades, true, LAMBDA( + for (int j = 0; j < 2; j++) + { + if (it.m_projectile[j] == proj) return it; + } + )); + return NADE_TYPE_Null; + } + + entity Nade_TrailEffect(int proj, int nade_team) + { + switch (proj) + { + case PROJECTILE_NADE: return EFFECT_NADE_TRAIL(nade_team); + case PROJECTILE_NADE_BURN: return EFFECT_NADE_TRAIL_BURN(nade_team); + } + + FOREACH(Nades, true, LAMBDA( + for (int j = 0; j < 2; j++) + { + if (it.m_projectile[j] == proj) + { + string trail = it.m_trail[j].eent_eff_name; + if (trail) return it.m_trail[j]; + break; + } + } + )); + + return EFFECT_Null; + } ++#endif + + #include "all.inc" + + #endif diff --cc qcsrc/common/vehicles/vehicle.qh index a9e247f602,80787b4ae6..f38490ca43 --- a/qcsrc/common/vehicles/vehicle.qh +++ b/qcsrc/common/vehicles/vehicle.qh @@@ -36,9 -32,41 +32,45 @@@ CLASS(Vehicle, Object /** vehicle hitbox size */ ATTRIB(Vehicle, maxs, vector, '0 0 0') + METHOD(Vehicle, display, void(entity this, void(string name, string icon) returns)) { + returns(this.vehicle_name, this.m_icon ? sprintf("/gfx/hud/%s/%s", cvar_string("menu_skin"), this.m_icon) : string_null); + } ++ + /** (BOTH) setup vehicle data */ + METHOD(Vehicle, vr_setup, void(Vehicle)) { } + /** (SERVER) logic to run every frame */ + METHOD(Vehicle, vr_think, void(Vehicle)) { } + /** (SERVER) called when vehicle dies */ + METHOD(Vehicle, vr_death, void(Vehicle)) { } + /** (BOTH) precaches models/sounds used by this vehicle */ + METHOD(Vehicle, vr_precache, void(Vehicle)) { } + /** (SERVER) called when a player enters this vehicle */ + METHOD(Vehicle, vr_enter, void(Vehicle)) { } + /** (SERVER) called when the vehicle re-spawns */ + METHOD(Vehicle, vr_spawn, void(Vehicle)) { } + /** (SERVER) called when a vehicle hits something */ + METHOD(Vehicle, vr_impact, void(Vehicle)) { } + /** (CLIENT) logic to run every frame */ + METHOD(Vehicle, vr_hud, void(Vehicle)) { } ENDCLASS(Vehicle) + // vehicle spawn flags (need them here for common registrations) + const int VHF_ISVEHICLE = 2; /// Indicates vehicle + const int VHF_HASSHIELD = 4; /// Vehicle has shileding + const int VHF_SHIELDREGEN = 8; /// Vehicles shield regenerates + const int VHF_HEALTHREGEN = 16; /// Vehicles health regenerates + const int VHF_ENERGYREGEN = 32; /// Vehicles energy regenerates + const int VHF_DEATHEJECT = 64; /// Vehicle ejects pilot upon fatal damage + const int VHF_MOVE_GROUND = 128; /// Vehicle moves on gound + const int VHF_MOVE_HOVER = 256; /// Vehicle hover close to gound + const int VHF_MOVE_FLY = 512; /// Vehicle is airborn + const int VHF_DMGSHAKE = 1024; /// Add random velocity each frame if health < 50% + const int VHF_DMGROLL = 2048; /// Add random angles each frame if health < 50% + const int VHF_DMGHEADROLL = 4096; /// Add random head angles each frame if health < 50% + const int VHF_MULTISLOT = 8192; /// Vehicle has multiple player slots + const int VHF_PLAYERSLOT = 16384; /// This ent is a player slot on a multi-person vehicle + + // fields: + .entity tur_head; + #endif diff --cc qcsrc/menu/xonotic/dialog_multiplayer_media.qc index f37b36a677,abecd1ed5b..40c434aff7 --- a/qcsrc/menu/xonotic/dialog_multiplayer_media.qc +++ b/qcsrc/menu/xonotic/dialog_multiplayer_media.qc @@@ -25,9 -25,7 +25,8 @@@ void XonoticMediaTab_fill(entity me mc = makeXonoticTabController(me.rows - 2); me.gotoRC(me, 0.5, 0); + me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Guide"), NEW(XonoticGuideTab))); - me.TD(me, 1, 1, e = mc.makeTabButton_T(mc, _("Demos"), makeXonoticDemoBrowserTab(), - _("Browse and view demos"))); + me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Demos"), makeXonoticDemoBrowserTab())); me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Screenshots"), makeXonoticScreenshotBrowserTab())); me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Music Player"), makeXonoticMusicPlayerTab())); diff --cc qcsrc/menu/xonotic/guide/pages.qh index 86150af5ff,0000000000..8654b2529f mode 100644,000000..100644 --- a/qcsrc/menu/xonotic/guide/pages.qh +++ b/qcsrc/menu/xonotic/guide/pages.qh @@@ -1,32 -1,0 +1,29 @@@ +#ifndef GUIDE_PAGES_H +#define GUIDE_PAGES_H + +CLASS(GuidePage, Object); + ATTRIB(GuidePage, m_id, int, 0); + ATTRIB(GuidePage, m_title, string, ""); + ATTRIB(GuidePage, m_description, string, ""); + METHOD(GuidePage, describe, string(GuidePage this)) { + return this.m_description; + } + METHOD(GuidePage, display, void(GuidePage this, void(string name, string icon) returns)) { + returns(this.m_title, "nopreview_map"); + } + CONSTRUCTOR(GuidePage, string _title) { + CONSTRUCT(GuidePage); + this.m_title = _title; + } +ENDCLASS(GuidePage) + - void RegisterGuidePages(); - const int GUIDE_PAGES_MAX = 16; - entity GUIDE_PAGES[GUIDE_PAGES_MAX], GUIDE_PAGES_first, GUIDE_PAGES_last; - int GUIDE_PAGES_COUNT; ++REGISTRY(GuidePages, 16) +#define REGISTER_GUIDE_PAGE(id, title) \ - REGISTER(RegisterGuidePages, GUIDE_PAGE, GUIDE_PAGES, GUIDE_PAGES_COUNT, id, m_id, NEW(GuidePage, title)) ++ REGISTER(RegisterGuidePages, GUIDE_PAGE, GuidePages, id, m_id, NEW(GuidePage, title)) +REGISTER_REGISTRY(RegisterGuidePages) + +REGISTER_GUIDE_PAGE(0, _("Intro")) { this.m_description = _( +"Welcome to xonotic" +);} + +#endif diff --cc qcsrc/menu/xonotic/guide/tab.qc index 209abc80fe,0000000000..8d4b886769 mode 100644,000000..100644 --- a/qcsrc/menu/xonotic/guide/tab.qc +++ b/qcsrc/menu/xonotic/guide/tab.qc @@@ -1,230 -1,0 +1,230 @@@ +#ifndef DIALOG_MEDIA_GUIDE_H +#define DIALOG_MEDIA_GUIDE_H +#include "../datasource.qc" + +#define TOPICS(X) \ + X(NEW(FreetextSource), _("Guide"), "gametype_tdm") \ + X(NEW(GametypeSource), _("Gametypes"), "gametype_dm") \ + X(NEW(WeaponSource), _("Weapons"), "gametype_ka") \ + X(NEW(ItemSource), _("Items"), "gametype_kh") \ + X(NEW(BuffSource), _("Buffs"), "gametype_dom") \ + X(NEW(NadeSource), _("Nades"), "gametype_ft") \ + X(NEW(MonsterSource), _("Monsters"), "gametype_lms") \ + X(NEW(VehicleSource), _("Vehicles"), "gametype_rc") \ + X(NEW(TurretSource), _("Turrets"), "gametype_as") \ + X(NEW(MutatorSource), _("Mutators"), "gametype_nb") \ + X(NEW(MapSource), _("Maps"), "gametype_ctf") \ + if (cvar("developer")) X(NEW(DebugSource), _("Debug"), "gametype_ons") \ + /**/ +CLASS(TopicSource, DataSource) + METHOD(TopicSource, getEntry, entity(TopicSource this, int i, void(string, string) returns)) { + int idx = 0; + #define TOPIC(src, name, icon) if (idx++ == i) { if (returns) returns(name, icon); return DataSource_true; } + TOPICS(TOPIC); + #undef TOPIC + if (returns) returns("undefined", "undefined"); + return DataSource_false; + } + METHOD(TopicSource, reload, int(TopicSource this, string filter)) { + int n = 0; + #define TOPIC(src, name, icon) n++; + TOPICS(TOPIC); + #undef TOPIC + return n; + } +ENDCLASS(TopicSource) + +CLASS(DebugSource, DataSource) + .entity nextdebug; + entity find_debug() { + entity head = NULL, tail = NULL; + for (entity it = NULL; (it = nextent(it)); ) { + if (!it.instanceOfObject) continue; + if (it.instanceOfItem) continue; + if (it.instanceOfAnimHost) continue; + if (it.instanceOfDataSource) continue; + if (it.classname == "Object") continue; + if (it.classname == "vtbl") continue; + if (!tail) { + tail = head = it; + } else { + tail.nextdebug = it; + tail = it; + } + } + return head; + } + string DebugSource_activeFilter = ""; + METHOD(DebugSource, getEntry, entity(DebugSource this, int i, void(string, string) returns)) { + int idx = 0; + entity e; + for (e = find_debug(); e; e = e.nextdebug) { + if (strstrofs(sprintf("entity %i", e), DebugSource_activeFilter, 0) < 0) continue; + if (idx++ == i) break; + } + if (returns) e.display(e, returns); + return e; + } + METHOD(DebugSource, reload, int(DebugSource this, string filter)) { + DebugSource_activeFilter = filter; + int idx = 0; + entity e; + for (e = find_debug(); e; e = e.nextdebug) { + if (strstrofs(sprintf("entity %i", e), DebugSource_activeFilter, 0) < 0) continue; + idx++; + } + return idx; + } +ENDCLASS(DebugSource) + - #define REGISTRY_SOURCE(id, arr, count) \ ++#define REGISTRY_SOURCE(id, arr) \ +CLASS(id, DataSource) \ + METHOD(id, getEntry, entity(id this, int i, void(string, string) returns)) { \ + entity e = arr[i]; \ + if (returns) e.display(e, returns); \ + return e; \ + } \ - METHOD(id, reload, int(id this, string filter)) { return count; } \ ++ METHOD(id, reload, int(id this, string filter)) { return arr##_COUNT; } \ +ENDCLASS(id) + +#include "pages.qh" - REGISTRY_SOURCE(FreetextSource, GUIDE_PAGES, GUIDE_PAGES_COUNT) ++REGISTRY_SOURCE(FreetextSource, GuidePages) + +#include "../../../common/mapinfo.qh" - REGISTRY_SOURCE(GametypeSource, MAPINFO_TYPES, MAPINFO_TYPE_COUNT) ++REGISTRY_SOURCE(GametypeSource, Gametypes) + +#include "../../../common/items/all.qh" - REGISTRY_SOURCE(ItemSource, ITEMS, ITEM_COUNT) ++REGISTRY_SOURCE(ItemSource, Items) + - #include "../../../common/buffs.qh" - REGISTRY_SOURCE(BuffSource, BUFFS, BUFFS_COUNT) ++#include "../../../common/buffs/all.qh" ++REGISTRY_SOURCE(BuffSource, Buffs) + - #include "../../../common/nades.qh" - REGISTRY_SOURCE(NadeSource, NADES, NADES_COUNT) ++#include "../../../common/nades/all.qh" ++REGISTRY_SOURCE(NadeSource, Nades) + +#include "../../../common/weapons/all.qh" - REGISTRY_SOURCE(WeaponSource, weapon_info, WEP_COUNT) ++REGISTRY_SOURCE(WeaponSource, Weapons) + +#include "../../../common/monsters/all.qh" - REGISTRY_SOURCE(MonsterSource, monster_info, MON_COUNT) ++REGISTRY_SOURCE(MonsterSource, Monsters) + +#include "../../../common/vehicles/all.qh" - REGISTRY_SOURCE(VehicleSource, vehicle_info, VEH_COUNT) ++REGISTRY_SOURCE(VehicleSource, Vehicles) + +#include "../../../common/turrets/all.qh" - REGISTRY_SOURCE(TurretSource, turret_info, TUR_COUNT) ++REGISTRY_SOURCE(TurretSource, Turrets) + +#include "../../../common/mutators/base.qh" - REGISTRY_SOURCE(MutatorSource, MUTATORS, MUTATORS_COUNT) ++REGISTRY_SOURCE(MutatorSource, MUTATORS) + +CLASS(MapSource, DataSource) + METHOD(MapSource, getEntry, entity(MapSource this, int i, void(string, string) returns)) { + if (!MapInfo_Get_ByID(i)) return DataSource_false; + string path = strcat("/maps/", MapInfo_Map_bspname); + string img = draw_PictureSize(path) ? path : "nopreview_map"; + if (returns) returns(MapInfo_Map_titlestring, img); + MapInfo_ClearTemps(); + return DataSource_true; + } + METHOD(MapSource, indexOf, int(MapSource this, string s)) { + MapInfo_FindName(s); + return MapInfo_FindName_firstResult; + } + METHOD(MapSource, reload, int(MapSource this, string s)) { + MapInfo_FilterGametype(MAPINFO_TYPE_ALL, 0, 0, 0, 0); + if (s) MapInfo_FilterString(s); + return MapInfo_count; + } + METHOD(MapSource, destroy, void(MapSource this)) { MapInfo_Shutdown(); } +ENDCLASS(MapSource) + +#include "topics.qc" +#include "entries.qc" +#include "description.qc" +#include "../tab.qc" +CLASS(XonoticGuideTab, XonoticTab) + ATTRIB(XonoticGuideTab, rows, float, 21) + ATTRIB(XonoticGuideTab, columns, float, 6) + ATTRIB(XonoticGuideTab, intendedWidth, float, 1) + METHOD(XonoticGuideTab, fill, void(entity)); + METHOD(XonoticGuideTab, topicChangeNotify, void(entity, entity)); + METHOD(XonoticGuideTab, entryChangeNotify, void(entity, entity)); + + ATTRIB(XonoticGuideTab, topicList, entity, NEW(XonoticTopicList, NEW(TopicSource))) + ATTRIB(XonoticGuideTab, entryList, entity, NEW(XonoticEntryList, NULL)) + ATTRIB(XonoticGuideTab, descriptionPane, entity, NEW(XonoticGuideDescription)) + + INIT(XonoticGuideTab) { + this.configureDialog(this); + } +ENDCLASS(XonoticGuideTab) +#endif + +#ifdef IMPLEMENTATION + +void XonoticGuideTab_fill(entity this) +{ + entity topics = this.topicList; + topics.onChange = XonoticGuideTab_topicChangeNotify; + topics.onChangeEntity = this; + entity entries = this.entryList; + entries.onChange = XonoticGuideTab_entryChangeNotify; + entries.onChangeEntity = this; + entity filter = entries.stringFilterBox = makeXonoticInputBox(false, string_null); + filter.keyDown = MapList_StringFilterBox_keyDown; + filter.onChange = MapList_StringFilterBox_Change; + filter.onChangeEntity = entries; + entries.controlledTextbox = filter; + entity description = this.descriptionPane; + + int + col = 0, width = 1.5; + this.gotoRC(this, 0, col); + this.TD(this, 1, width, makeXonoticHeaderLabel(_("Topic"))); + this.TR(this); + this.TD(this, this.rows - 1, width, topics); + + col += width, width = 2; + this.gotoRC(this, 0, col); this.setFirstColumn(this, this.currentColumn); + this.TD(this, 1, width, makeXonoticHeaderLabel(_("Entry"))); + this.TR(this); + this.TD(this, this.rows - 1 - 1, width, entries); + this.gotoRC(this, this.rows - 1, col); + this.TD(this, 1, 0.3, makeXonoticTextLabel(0, _("Filter:"))); + this.TD(this, 1, width - 0.3, filter); + + col += width, width = 2.5; + this.gotoRC(this, 0, col); this.setFirstColumn(this, this.currentColumn); + this.TD(this, 1, width, makeXonoticHeaderLabel(_("Description"))); + this.TR(this); + this.TD(this, this.rows - 1, width, description); + + this.topicChangeNotify(topics, this); +} + +void XonoticGuideTab_topicChangeNotify(entity, entity this) +{ + entity topics = this.topicList; + entity entries = this.entryList; + int i = topics.selectedItem; + int idx = 0; + entity found = NULL; + #define TOPIC(src, name, icon) if (idx++ == i) { static entity e; if (!e) e = src; found = e; break; } + do { TOPICS(TOPIC); } while (0); + #undef TOPIC + entries.source = found; + entries.refilter(entries); + entries.setSelected(entries, 0); +} + +void XonoticGuideTab_entryChangeNotify(entity, entity this) +{ + entity desc = this.descriptionPane; + entity entries = this.entryList; + entity e = entries.source.getEntry(entries.source, entries.selectedItem, func_null); + string s = e.describe(e); + if (cvar("developer")) { s = sprintf("entity %i\n%s", e, s); } + desc.setDescription(desc, s); +} + +#endif