diff --git a/cvarinfo.txt b/cvarinfo.txt index da73f47a9..e3045d576 100644 --- a/cvarinfo.txt +++ b/cvarinfo.txt @@ -43,5 +43,5 @@ server bool swwm_upgradebosses = true; // vanilla bosses will be "upgraded" to server bool swwm_extraalert = false; // enables A_AlertMonsters calls for certain things which may be cpu-heavy user bool swwm_accdamage = false; // damage within the same tic is grouped into a single damage number user int swwm_maxtargets = 40; // maximum targeter healthbars to display (0 = unlimited) -user int swwm_maxscorenums = 20; // maximum score numbers to display (0 = unlimited) -user int swwm_maxdamnums = 40; // maximum damage/healing numbers to display (0 = unlimited) +user int swwm_maxscorenums = 0; // maximum score numbers to display (0 = unlimited) +user int swwm_maxdamnums = 0; // maximum damage/healing numbers to display (0 = unlimited) diff --git a/language.def_menu b/language.def_menu index cd64ca0b8..d7cc50997 100644 --- a/language.def_menu +++ b/language.def_menu @@ -120,9 +120,9 @@ TOOLTIP_SWWM_BOSSHEALTHBARS = "Show a healthbar for vanilla boss encounters at t TOOLTIP_SWWM_UPGRADEBOSSES = "Buffs the health of vanilla bosses in order to make the fights more \"fair\" with this mod, and less prone to instant wins."; TOOLTIP_SWWM_EXTRAALERT = "Allows monsters to hear things such as bouncing projectiles, ricocheting bullets, and more. Due to the recursive nature of the A_AlertMonsters function, this has a MASSIVE performance hit on very complex maps."; TOOLTIP_SWWM_ACCDAMAGE = "Damage dealt to a target within the same tic will be grouped into a single damage number, which may make the screen less cluttered in most cases."; -TOOLTIP_SWWM_MAXTARGETS = "Limit the amount of healthbars to display on-screen. Helps keep the screen less cluttered, and may even improve performance."; -TOOLTIP_SWWM_MAXDAMNUMS = "Limit the amount of damage/healing numbers to display on-screen. Helps keep the screen less cluttered, and may even improve performance."; -TOOLTIP_SWWM_MAXSCORENUMS = "Limit the amount of score numbers to display on-screen. Helps keep the screen less cluttered, and may even improve performance."; +TOOLTIP_SWWM_MAXTARGETS = "Limit the amount of healthbars to display on-screen. Helps keep the screen less cluttered."; +TOOLTIP_SWWM_MAXDAMNUMS = "Limit the amount of damage/healing numbers to display on-screen. Helps keep the screen less cluttered."; +TOOLTIP_SWWM_MAXSCORENUMS = "Limit the amount of score numbers to display on-screen. Helps keep the screen less cluttered."; // knowledge base SWWM_COMINGSOON = "(coming soon)"; SWWM_MISSTAB = "Mission"; diff --git a/language.es_menu b/language.es_menu index 7868368be..73ee4a85b 100644 --- a/language.es_menu +++ b/language.es_menu @@ -117,9 +117,9 @@ TOOLTIP_SWWM_BOSSHEALTHBARS = "Muestra una barra de vida para bosses vanilla en TOOLTIP_SWWM_UPGRADEBOSSES = "Incrementa la salud de bosses vanilla para hacer que las peleas sean más \"justas\" con este mod, y no tan propensas a ganarse al instante."; TOOLTIP_SWWM_EXTRAALERT = "Permite a los enemigos oir cosas como proyectiles y balas rebotando, entre otros. Debido a la naturaleza recursiva de la función A_AlertMonsters, esto puede tener un impacto MASIVO en el rendimiento en mapas muy complejos."; TOOLTIP_SWWM_ACCDAMAGE = "El daño hecho a un objetivo en el mismo tic será agrupado en un único número, lo cual resultará en una pantalla más despejada en la mayoría de casos."; -TOOLTIP_SWWM_MAXTARGETS = "Limita la cantidad de barras de salud a mostrar en pantalla. Ayuda a mantener la pantalla más despejada, y puede incluso mejorar el rendimiento."; -TOOLTIP_SWWM_MAXDAMNUMS = "Limita la cantidad de números de daño/curación a mostrar en pantalla. Ayuda a mantener la pantalla más despejada, y puede incluso mejorar el rendimiento."; -TOOLTIP_SWWM_MAXSCORENUMS = "Limita la cantidad de números de puntuación a mostrar en pantalla. Ayuda a mantener la pantalla más despejada, y puede incluso mejorar el rendimiento."; +TOOLTIP_SWWM_MAXTARGETS = "Limita la cantidad de barras de salud a mostrar en pantalla. Ayuda a mantener la pantalla más despejada."; +TOOLTIP_SWWM_MAXDAMNUMS = "Limita la cantidad de números de daño/curación a mostrar en pantalla. Ayuda a mantener la pantalla más despejada."; +TOOLTIP_SWWM_MAXSCORENUMS = "Limita la cantidad de números de puntuación a mostrar en pantalla. Ayuda a mantener la pantalla más despejada."; // knowledge base SWWM_COMINGSOON = "(próximamente)"; SWWM_MISSTAB = "Misión"; diff --git a/menudef.txt b/menudef.txt index caea7ec62..d1e9f80fa 100644 --- a/menudef.txt +++ b/menudef.txt @@ -46,9 +46,9 @@ OptionMenu "SWWMOptionMenu" Option "$SWWM_ACCDAMAGE", "swwm_accdamage", "YesNo" Option "$SWWM_SCORENUMS", "swwm_scorenums", "YesNo" Option "$SWWM_SCOREBONUS", "swwm_scorebonus", "YesNo" - ScaleSlider "$SWWM_MAXTARGETS", "swwm_maxtargets", 0, 100, 1, "$SWWM_UNLIMITED" - ScaleSlider "$SWWM_MAXDAMNUMS", "swwm_maxdamnums", 0, 100, 1, "$SWWM_UNLIMITED" - ScaleSlider "$SWWM_MAXSCORENUMS", "swwm_maxscorenums", 0, 100, 1, "$SWWM_UNLIMITED" + ScaleSlider "$SWWM_MAXTARGETS", "swwm_maxtargets", 0, 1000, 1, "$SWWM_UNLIMITED" + ScaleSlider "$SWWM_MAXDAMNUMS", "swwm_maxdamnums", 0, 1000, 1, "$SWWM_UNLIMITED" + ScaleSlider "$SWWM_MAXSCORENUMS", "swwm_maxscorenums", 0, 1000, 1, "$SWWM_UNLIMITED" Option "$SWWM_SHADERS", "swwm_shaders", "YesNo" Option "$SWWM_INTERTYPE", "swwm_intertype", "SWWMInterType" StaticText " " diff --git a/zscript/swwm_ammo.zsc b/zscript/swwm_ammo.zsc index 6a16736ac..37f462fc7 100644 --- a/zscript/swwm_ammo.zsc +++ b/zscript/swwm_ammo.zsc @@ -21,13 +21,6 @@ Mixin Class SWWMAmmo return copy; } - private bool CmpAmmo( Class a, Class b ) - { - let amta = GetDefaultByType(a).Amount; - let amtb = GetDefaultByType(b).Amount; - return (amta < amtb); - } - override bool SpecialDropAction( Actor dropper ) { if ( Amount != default.Amount ) @@ -40,6 +33,40 @@ Mixin Class SWWMAmmo return false; } + private bool CmpAmmo( Class a, Class b ) + { + let amta = GetDefaultByType(a).Amount; + let amtb = GetDefaultByType(b).Amount; + return (amta < amtb); + } + + private int partition_ammotypes( Array > a, int l, int h ) + { + Class pv = a[h]; + int i = (l-1); + for ( int j=l; j<=(h-1); j++ ) + { + if ( CmpAmmo(pv,a[j]) ) + { + i++; + Class tmp = a[j]; + a[j] = a[i]; + a[i] = tmp; + } + } + Class tmp = a[h]; + a[h] = a[i+1]; + a[i+1] = tmp; + return i+1; + } + private void qsort_ammotypes( Array > a, int l, int h ) + { + if ( l >= h ) return; + int p = partition_ammotypes(a,l,h); + qsort_ammotypes(a,l,p-1); + qsort_ammotypes(a,p+1,h); + } + override inventory CreateTossable( int amt ) { if ( bUndroppable || bUntossable || !Owner || (Amount <= 0) || (amt == 0) ) @@ -55,22 +82,7 @@ Mixin Class SWWMAmmo ammotypes.Push((Class)(AllActorClasses[i])); } // sort from largest to smallest - for ( int i=0; i 0) && CmpAmmo(ammotypes[k-1],ammotypes[k]) ) - { - Class tmp = ammotypes[k]; - ammotypes[k] = ammotypes[k-1]; - ammotypes[k-1] = tmp; - k--; - } - j++; - } - } + qsort_ammotypes(ammotypes,0,ammotypes.Size()-1); // perform subdivision Inventory last = null; while ( amt > 0 ) diff --git a/zscript/swwm_hud.zsc b/zscript/swwm_hud.zsc index c4bf39b7e..48d2981f3 100644 --- a/zscript/swwm_hud.zsc +++ b/zscript/swwm_hud.zsc @@ -191,6 +191,90 @@ Class SWWMStatusBar : BaseStatusBar return (dista < distb); } + // quicksort (points of interest) + private int partition_intpoints( Array a, int l, int h ) + { + SWWMInterest pv = a[h]; + int i = (l-1); + for ( int j=l; j<=(h-1); j++ ) + { + if ( CmpInterest(pv,a[j]) || CmpDist(pv.pos,a[j].pos) ) + { + i++; + SWWMInterest tmp = a[j]; + a[j] = a[i]; + a[i] = tmp; + } + } + SWWMInterest tmp = a[h]; + a[h] = a[i+1]; + a[i+1] = tmp; + return i+1; + } + private void qsort_intpoints( Array a, int l, int h ) + { + if ( l >= h ) return; + int p = partition_intpoints(a,l,h); + qsort_intpoints(a,l,p-1); + qsort_intpoints(a,p+1,h); + } + + // quicksort (combat trackers) + private int partition_trackers( Array a, int l, int h ) + { + SWWMCombatTracker pv = a[h]; + int i = (l-1); + for ( int j=l; j<=(h-1); j++ ) + { + if ( CmpTarget(pv,a[j]) || CmpDist(pv.pos,a[j].pos) ) + { + i++; + SWWMCombatTracker tmp = a[j]; + a[j] = a[i]; + a[i] = tmp; + } + } + SWWMCombatTracker tmp = a[h]; + a[h] = a[i+1]; + a[i+1] = tmp; + return i+1; + } + private void qsort_trackers( Array a, int l, int h ) + { + if ( l >= h ) return; + int p = partition_trackers(a,l,h); + qsort_trackers(a,l,p-1); + qsort_trackers(a,p+1,h); + } + + // quicksort (score objects) + private int partition_scoreobjs( Array a, int l, int h ) + { + SWWMScoreObj pv = a[h]; + int i = (l-1); + for ( int j=l; j<=(h-1); j++ ) + { + if ( CmpScore(pv,a[j]) || CmpDist(pv.pos,a[j].pos) ) + { + i++; + SWWMScoreObj tmp = a[j]; + a[j] = a[i]; + a[i] = tmp; + } + } + SWWMScoreObj tmp = a[h]; + a[h] = a[i+1]; + a[i+1] = tmp; + return i+1; + } + private void qsort_scoreobjs( Array a, int l, int h ) + { + if ( l >= h ) return; + int p = partition_scoreobjs(a,l,h); + qsort_scoreobjs(a,l,p-1); + qsort_scoreobjs(a,p+1,h); + } + override void Tick() { Super.Tick(); @@ -251,30 +335,19 @@ Class SWWMStatusBar : BaseStatusBar int i = 0; for ( SWWMInterest poi=hnd.intpoints; poi; poi=poi.next ) { - if ( viewvec dot level.Vec3Diff(viewpos,poi.pos) < 0 ) continue; + // ignore points clearly outside of player view + Vector3 tdir = level.Vec3Diff(viewpos,poi.pos); + if ( viewvec dot tdir < 0 ) continue; + proj.ProjectWorldPos(viewpos+tdir); + proj.ProjectToNormal(); + if ( !proj.IsInFront() || !proj.IsInScreen() ) continue; intpoints[i++] = poi; } // squeeze if some were discarded if ( i != hnd.intpoints_cnt ) intpoints.Resize(i); // sort by distance - sz = intpoints.Size(); - for ( int i=0; i 0) && (CmpInterest(intpoints[k-1],intpoints[k]) || CmpDist(intpoints[k-1].pos,intpoints[k].pos)) ) - { - SWWMInterest tmp = intpoints[k]; - intpoints[k] = intpoints[k-1]; - intpoints[k-1] = tmp; - k--; - } - j++; - } - } + qsort_intpoints(intpoints,0,intpoints.Size()-1); } if ( targetter.GetBool() ) { @@ -282,7 +355,7 @@ Class SWWMStatusBar : BaseStatusBar if ( trackers.Size() != hnd.trackers_cnt ) trackers.Resize(hnd.trackers_cnt); int i = 0; - for ( SWWMCombatTracker trk=hnd.trackers; trk && (!maxtargetnum||(i 0) ) mtime += 105; if ( level.maptime > trk.updated+mtime ) continue; // ignore trackers clearly outside of player view - if ( viewvec dot level.Vec3Diff(viewpos,trk.pos) < 0 ) continue; + Vector3 tdir = level.Vec3Diff(viewpos,trk.pos); + if ( viewvec dot tdir < 0 ) continue; + proj.ProjectWorldPos(viewpos+tdir); + proj.ProjectToNormal(); + if ( !proj.IsInFront() || !proj.IsInScreen() ) continue; trackers[i++] = trk; } // squeeze if some were discarded if ( i != hnd.trackers_cnt ) trackers.Resize(i); - sz = trackers.Size(); // sort by distance (give priority to players) - for ( int i=0; i maxtargetnum) ) { - int j = 1; - while ( j < sz ) - { - int k = j; - while ( (k > 0) && (CmpTarget(trackers[k-1],trackers[k]) || CmpDist(trackers[k-1].pos,trackers[k].pos)) ) - { - SWWMCombatTracker tmp = trackers[k]; - trackers[k] = trackers[k-1]; - trackers[k-1] = tmp; - k--; - } - j++; - } + int endo = trackers.Size()-maxtargetnum; + // we gotta push the frontmost bars to the start, due to the inverted draw order + for ( int i=maxtargetnum-1; i>=0; i-- ) + trackers[i] = trackers[endo+i]; + trackers.Resize(maxtargetnum); } } else trackers.Clear(); @@ -328,7 +398,12 @@ Class SWWMStatusBar : BaseStatusBar { for ( SWWMScoreObj scr=hnd.scorenums; scr && (i 0) && (CmpScore(scoreobjs[k-1],scoreobjs[k]) || CmpDist(scoreobjs[k-1].pos,scoreobjs[k].pos)) ) - { - SWWMScoreObj tmp = scoreobjs[k]; - scoreobjs[k] = scoreobjs[k-1]; - scoreobjs[k-1] = tmp; - k--; - } - j++; - } - } + qsort_scoreobjs(scoreobjs,0,scoreobjs.Size()-1); } override void Init() @@ -452,7 +516,6 @@ Class SWWMStatusBar : BaseStatusBar } } // targetting array - int displayed = 0; for ( int i=0; i a, int l, int h ) + { + Inventory pv = a[h]; + int i = (l-1); + for ( int j=l; j<=(h-1); j++ ) + { + if ( CmpInventory(pv,a[j]) ) + { + i++; + Inventory tmp = a[j]; + a[j] = a[i]; + a[i] = tmp; + } + } + Inventory tmp = a[h]; + a[h] = a[i+1]; + a[i+1] = tmp; + return i+1; + } + private void qsort_inventory( Array a, int l, int h ) + { + if ( l >= h ) return; + int p = partition_inventory(a,l,h); + qsort_inventory(a,l,p-1); + qsort_inventory(a,p+1,h); + } + + private int partition_store( Array > a, Array b, int l, int h ) + { + Class pv = a[h]; + int i = (l-1); + for ( int j=l; j<=(h-1); j++ ) + { + if ( CmpInventoryClass(pv,a[j]) ) + { + i++; + Class tmp = a[j]; + a[j] = a[i]; + a[i] = tmp; + int tmpi = b[j]; + b[j] = b[i]; + b[i] = tmpi; + } + } + Class tmp = a[h]; + a[h] = a[i+1]; + a[i+1] = tmp; + int tmpi = b[h]; + b[h] = b[i+1]; + b[i+1] = tmpi; + return i+1; + } + private void qsort_store( Array > a, Array b, int l, int h ) + { + if ( l >= h ) return; + int p = partition_store(a,b,l,h); + qsort_store(a,b,l,p-1); + qsort_store(a,b,p+1,h); } override void Ticker() @@ -1405,22 +1465,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu invlist.Push(inv); } // re-sort by category - for ( int i=0; i 0) && CmpInventory(invlist[k-1],invlist[k]) ) - { - Inventory tmp = invlist[k]; - invlist[k] = invlist[k-1]; - invlist[k-1] = tmp; - k--; - } - j++; - } - } + qsort_inventory(invlist,0,invlist.Size()-1); } else if ( curtab == TAB_KEYS ) { @@ -1515,25 +1560,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu storeunits.Push(amt); } // re-sort by category - for ( int i=0; i 0) && CmpInventoryClass(storelist[k-1],storelist[k]) ) - { - Class tmp = storelist[k]; - storelist[k] = storelist[k-1]; - storelist[k-1] = tmp; - int tmpi = storeunits[k]; - storeunits[k] = storeunits[k-1]; - storeunits[k-1] = tmpi; - k--; - } - j++; - } - } + qsort_store(storelist,storeunits,0,storelist.Size()-1); } else if ( curtab == TAB_LIBRARY ) { @@ -1598,22 +1625,7 @@ Class SWWMKnowledgeBaseMenu : GenericMenu invlist.Push(inv); } // re-sort by category - for ( int i=0; i 0) && CmpInventory(invlist[k-1],invlist[k]) ) - { - Inventory tmp = invlist[k]; - invlist[k] = invlist[k-1]; - invlist[k-1] = tmp; - k--; - } - j++; - } - } + qsort_inventory(invlist,0,invlist.Size()-1); } } // check if use succeeded