mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-24 00:00:13 +00:00
Restructure inventory UI, add vendor selling, camera intro on all spawns, and quest log
Split inventory into bags-only (B key) and character screen (C key). Vendor window auto-opens bags with sell prices on hover and right-click to sell. Add camera intro pan on all login/spawn/teleport/hearthstone events and idle orbit after 2 minutes. Add quest log UI, SMSG_MONSTER_MOVE handling, deferred creature spawn queue, and creature fade-in/movement interpolation for online mode.
This commit is contained in:
parent
a4a39c7f0f
commit
7128ea1417
21 changed files with 1092 additions and 149 deletions
|
|
@ -391,7 +391,8 @@ uint32_t Renderer::resolveMeleeAnimId() {
|
|||
return 0.0f;
|
||||
};
|
||||
|
||||
const uint32_t attackCandidates[] = {16, 17, 18, 19, 20, 21};
|
||||
// Prefer weapon attacks (1H=17, 2H=18) over unarmed (16); 19-21 are other variants
|
||||
const uint32_t attackCandidates[] = {17, 18, 16, 19, 20, 21};
|
||||
for (uint32_t id : attackCandidates) {
|
||||
if (characterRenderer->hasAnimation(characterInstanceId, id)) {
|
||||
meleeAnimId = id;
|
||||
|
|
@ -1032,6 +1033,113 @@ void Renderer::update(float deltaTime) {
|
|||
lastUpdateMs = std::chrono::duration<double, std::milli>(updateEnd - updateStart).count();
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Selection Circle
|
||||
// ============================================================
|
||||
|
||||
void Renderer::initSelectionCircle() {
|
||||
if (selCircleVAO) return;
|
||||
|
||||
// Minimal shader: position + uniform MVP + color
|
||||
const char* vsSrc = R"(
|
||||
#version 330 core
|
||||
layout(location = 0) in vec3 aPos;
|
||||
uniform mat4 uMVP;
|
||||
void main() {
|
||||
gl_Position = uMVP * vec4(aPos, 1.0);
|
||||
}
|
||||
)";
|
||||
const char* fsSrc = R"(
|
||||
#version 330 core
|
||||
uniform vec3 uColor;
|
||||
out vec4 FragColor;
|
||||
void main() {
|
||||
FragColor = vec4(uColor, 0.6);
|
||||
}
|
||||
)";
|
||||
|
||||
auto compile = [](GLenum type, const char* src) -> GLuint {
|
||||
GLuint s = glCreateShader(type);
|
||||
glShaderSource(s, 1, &src, nullptr);
|
||||
glCompileShader(s);
|
||||
return s;
|
||||
};
|
||||
|
||||
GLuint vs = compile(GL_VERTEX_SHADER, vsSrc);
|
||||
GLuint fs = compile(GL_FRAGMENT_SHADER, fsSrc);
|
||||
selCircleShader = glCreateProgram();
|
||||
glAttachShader(selCircleShader, vs);
|
||||
glAttachShader(selCircleShader, fs);
|
||||
glLinkProgram(selCircleShader);
|
||||
glDeleteShader(vs);
|
||||
glDeleteShader(fs);
|
||||
|
||||
// Build ring vertices (two concentric circles forming a strip)
|
||||
constexpr int SEGMENTS = 48;
|
||||
constexpr float INNER = 0.85f;
|
||||
constexpr float OUTER = 1.0f;
|
||||
std::vector<float> verts;
|
||||
for (int i = 0; i <= SEGMENTS; i++) {
|
||||
float angle = 2.0f * 3.14159265f * static_cast<float>(i) / static_cast<float>(SEGMENTS);
|
||||
float c = std::cos(angle), s = std::sin(angle);
|
||||
// Outer vertex
|
||||
verts.push_back(c * OUTER);
|
||||
verts.push_back(s * OUTER);
|
||||
verts.push_back(0.0f);
|
||||
// Inner vertex
|
||||
verts.push_back(c * INNER);
|
||||
verts.push_back(s * INNER);
|
||||
verts.push_back(0.0f);
|
||||
}
|
||||
selCircleVertCount = static_cast<int>((SEGMENTS + 1) * 2);
|
||||
|
||||
glGenVertexArrays(1, &selCircleVAO);
|
||||
glGenBuffers(1, &selCircleVBO);
|
||||
glBindVertexArray(selCircleVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, selCircleVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, verts.size() * sizeof(float), verts.data(), GL_STATIC_DRAW);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), nullptr);
|
||||
glEnableVertexAttribArray(0);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void Renderer::setSelectionCircle(const glm::vec3& pos, float radius, const glm::vec3& color) {
|
||||
selCirclePos = pos;
|
||||
selCircleRadius = radius;
|
||||
selCircleColor = color;
|
||||
selCircleVisible = true;
|
||||
}
|
||||
|
||||
void Renderer::clearSelectionCircle() {
|
||||
selCircleVisible = false;
|
||||
}
|
||||
|
||||
void Renderer::renderSelectionCircle(const glm::mat4& view, const glm::mat4& projection) {
|
||||
if (!selCircleVisible) return;
|
||||
initSelectionCircle();
|
||||
|
||||
glm::mat4 model = glm::translate(glm::mat4(1.0f), selCirclePos);
|
||||
model = glm::scale(model, glm::vec3(selCircleRadius));
|
||||
|
||||
glm::mat4 mvp = projection * view * model;
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
glUseProgram(selCircleShader);
|
||||
glUniformMatrix4fv(glGetUniformLocation(selCircleShader, "uMVP"), 1, GL_FALSE, &mvp[0][0]);
|
||||
glUniform3fv(glGetUniformLocation(selCircleShader, "uColor"), 1, &selCircleColor[0]);
|
||||
|
||||
glBindVertexArray(selCircleVAO);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, selCircleVertCount);
|
||||
glBindVertexArray(0);
|
||||
|
||||
glDepthMask(GL_TRUE);
|
||||
glEnable(GL_CULL_FACE);
|
||||
}
|
||||
|
||||
void Renderer::renderWorld(game::World* world) {
|
||||
auto renderStart = std::chrono::steady_clock::now();
|
||||
lastTerrainRenderMs = 0.0;
|
||||
|
|
@ -1157,6 +1265,9 @@ void Renderer::renderWorld(game::World* world) {
|
|||
characterRenderer->render(*camera, view, projection);
|
||||
}
|
||||
|
||||
// Render selection circle under targeted creature
|
||||
renderSelectionCircle(view, projection);
|
||||
|
||||
// Render WMO buildings (after characters, before UI)
|
||||
if (wmoRenderer && camera) {
|
||||
auto wmoStart = std::chrono::steady_clock::now();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue