Improve android research tree visual feedback

This commit is contained in:
DBotThePony 2022-08-31 14:00:12 +07:00
parent 3593dd8bbc
commit b00182fc6e
Signed by: DBot
GPG Key ID: DCC23B5715498507
3 changed files with 103 additions and 20 deletions

View File

@ -69,15 +69,18 @@ abstract class AndroidResearch(val type: AndroidResearchType<*>, val capability:
return false
}
if (!allPrerequisitesResearched || anyBlockerResearched) {
if (!isPrerequisitesResearched || isAnyBlockerResearched) {
return false
}
return true
}
val anyBlockerResearched: Boolean get() {
for (research in blockedBy) {
/**
* Determines if this research is already blocked directly by another research.
*/
val isAnyBlockerResearched: Boolean get() {
for (research in type.flatBlockedBy) {
if (capability.getResearch(research).isResearched) {
return true
}
@ -86,8 +89,46 @@ abstract class AndroidResearch(val type: AndroidResearchType<*>, val capability:
return false
}
val allPrerequisitesResearched: Boolean get() {
for (research in prerequisites) {
/**
* Determines if this research is already blocked by another research, directly or indirectly.
*
* This is slower than [isAnyBlockerResearched] and makes sense only to check this for visualization purposes,
* since indirect blocking research will just turn [isPrerequisitesResearched] false (under normal conditions).
*/
val isAnyBlockerResearchedIndirect: Boolean get() {
for (research in type.allBlockedBy) {
if (capability.getResearch(research).isResearched) {
return true
}
}
return false
}
/**
* Determines if this research' direct prerequisites are researched.
*/
val isPrerequisitesResearched: Boolean get() {
for (research in type.flatPrerequisites) {
if (!capability.getResearch(research).isResearched) {
return false
}
}
return true
}
/**
* Determines if this research' prerequisites are researched, direct or indirect.
*
* Doesn't make much sense to check for this, since all prerequisites *should* have their prerequisites
* researched and so on.
*
* Strictly speaking, if someone tamper with research tree and mark all direct prerequisites unlocked
* without unlocking their prerequisites, [isPrerequisitesResearched] will return true, but *this* will return *false*.
*/
val isPrerequisitesResearchedIndirect: Boolean get() {
for (research in type.allPrerequisites) {
if (!capability.getResearch(research).isResearched) {
return false
}
@ -152,9 +193,4 @@ abstract class AndroidResearch(val type: AndroidResearchType<*>, val capability:
override fun deserializeNBT(nbt: CompoundTag) {
isResearched = nbt.getBoolean("researched")
}
inline val prerequisites get() = type.flatPrerequisites
inline val unlocks get() = type.flatUnlocks
inline val blockedBy get() = type.flatBlockedBy
inline val blocking get() = type.flatBlocking
}

View File

@ -231,7 +231,7 @@ open class AndroidResearchType<R : AndroidResearch>(
*
* Returns list which also doubles as set (for contains method).
*/
val flatBlockedBy: List<AndroidResearchType<*>> by lazy {
val flatBlockedBy: ListSet<AndroidResearchType<*>> by lazy {
val list = ImmutableList.builder<AndroidResearchType<*>>()
for (blocker in definedBlockedBy) {
@ -252,6 +252,23 @@ open class AndroidResearchType<R : AndroidResearch>(
ListSet(list.build())
}
/**
* All research blocking this research, even indirect ones (e.g. blocked by through one of parent research).
*
* Returns list which also doubles as set (for contains method).
*/
val allBlockedBy: ListSet<AndroidResearchType<*>> by lazy {
val list = HashSet<AndroidResearchType<*>>()
list.addAll(flatBlockedBy)
for (parent in allPrerequisites) {
list.addAll(parent.flatBlockedBy)
}
ListSet(list)
}
/**
* All research directly unlocked by this research.
*

View File

@ -22,7 +22,6 @@ import ru.dbotthepony.mc.otm.client.render.drawColor
import ru.dbotthepony.mc.otm.client.render.drawLine
import ru.dbotthepony.mc.otm.client.render.drawRect
import ru.dbotthepony.mc.otm.client.screen.panels.*
import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel
import ru.dbotthepony.mc.otm.client.screen.widget.WidePowerGaugePanel
import ru.dbotthepony.mc.otm.core.RGBAColor
import ru.dbotthepony.mc.otm.ifPresentK
@ -294,6 +293,8 @@ private open class AndroidResearchButton(
AndroidStationScreen.RESEARCHED.setSystemColor()
} else if (node.canResearch) {
AndroidStationScreen.CAN_BE_RESEARCHED.setSystemColor()
} else if (node.isAnyBlockerResearchedIndirect) {
AndroidStationScreen.ALREADY_BLOCKED.setSystemColor()
} else {
AndroidStationScreen.CAN_NOT_BE_RESEARCHED.setSystemColor()
}
@ -310,7 +311,7 @@ private open class AndroidResearchButton(
RGBAColor.RED.setSystemColor()
Widgets18.CROSS.render(stack)
} else if (node.anyBlockerResearched) {
} else if (node.isAnyBlockerResearched) {
RGBAColor.RED.setSystemColor()
Widgets18.FORWARD_SLASH.render(stack)
@ -334,16 +335,44 @@ private open class AndroidResearchButton(
}
hovered ?: return
val lines = highlightLines[hovered.type] ?: return
val pathLines = highlightLines[hovered.type]
drawColor = RGBAColor.LIGHT_GREEN
if (pathLines != null) {
drawColor = RGBAColor.LIGHT_GREEN
for (line in lines) {
val (pos1, pos2) = line
val (x1, y1) = pos1
val (x2, y2) = pos2
for (line in pathLines) {
val (pos1, pos2) = line
val (x1, y1) = pos1
val (x2, y2) = pos2
drawLine(stack, x1, y1, x2, y2, 0.5f)
drawLine(stack, x1, y1, x2, y2, 0.5f)
}
}
// very lazy solution
val mark = Any()
val drawn = IdentityHashMap<LinePos, Any>()
for (blocker in hovered.type.allBlocking) {
val blockLines = highlightLines[blocker]
if (blockLines != null) {
drawColor = RGBAColor.RED
for (line in blockLines) {
if (drawn.containsKey(line)) {
continue
}
drawn[line] = mark
val (pos1, pos2) = line
val (x1, y1) = pos1
val (x2, y2) = pos2
drawLine(stack, x1, y1, x2, y2, 0.5f)
}
}
}
}
@ -494,5 +523,6 @@ class AndroidStationScreen constructor(p_97741_: AndroidStationMenu, p_97742_: I
val RESEARCHED = RGBAColor(150, 150, 200)
val CAN_BE_RESEARCHED = RGBAColor(150, 200, 150)
val CAN_NOT_BE_RESEARCHED = RGBAColor(200, 150, 150)
val ALREADY_BLOCKED = RGBAColor(105, 79, 79)
}
}