diff --git a/Resources/PakLocation.txt b/Resources/PakLocation.txt index ae8b0972..a0d6de42 100644 --- a/Resources/PakLocation.txt +++ b/Resources/PakLocation.txt @@ -1,6 +1,6 @@ All paks for development vesion: -http://yvt.jp/files/programs/osppaks/DevPaks3.zip +http://yvt.jp/files/programs/osppaks/DevPaks4.zip diff --git a/Sources/Client/Client.cpp b/Sources/Client/Client.cpp index e97fe081..7d4a0818 100644 --- a/Sources/Client/Client.cpp +++ b/Sources/Client/Client.cpp @@ -357,6 +357,8 @@ namespace spades { renderer->RegisterImage("Gfx/LoadingWindow.png"); renderer->RegisterImage("Gfx/LoadingWindowGlow.png"); renderer->RegisterImage("Gfx/LoadingStripe.png"); + renderer->RegisterImage("Gfx/HurtSprite.png"); + renderer->RegisterImage("Gfx/HurtRing.tga"); audioDevice->RegisterSound("Sounds/Feedback/Chat.wav"); SPLog("Started connecting to '%s'", hostname.c_str()); @@ -698,6 +700,19 @@ namespace spades { break; } + hurtSprites.resize(5); + float hpper = player->GetHealth() / 100.f; + for(size_t i = 0; i < hurtSprites.size(); i++) { + HurtSprite& spr = hurtSprites[i]; + spr.angle = GetRandom() * (2.f * M_PI); + spr.scale = .5f + GetRandom() * .3f; + spr.horzShift = GetRandom(); + spr.strength = .3f + GetRandom() * .7f; + if(hpper > .5f) { + spr.strength *= 1.5f - hpper; + } + } + audioDevice->PlayLocal(c, AudioParam()); }else{ lastHealth = player->GetHealth(); @@ -982,6 +997,13 @@ namespace spades { } } + if(name == "h" && down) { + // TODO: debug; remove this + int h = p->GetHealth(); + h -= 10; if(h <= 0) h = 100; + p->SetHP(h, HurtTypeWeapon, MakeVector3(0, 0, 0)); + } + if(CheckKey(cg_keyMoveLeft, name)){ playerInput.moveLeft = down; keypadInput.left = down; @@ -1274,6 +1296,13 @@ namespace spades { renderer->FrameDone(); Bitmap *bmp = renderer->ReadBitmap(); + // force 100% opacity + + uint32_t *pixels = bmp->GetPixels(); + for(size_t i = bmp->GetWidth() * bmp->GetHeight(); i > 0; i--) { + *(pixels++) |= 0xff000000UL; + } + try{ std::string name = ScreenShotPath(); bmp->Save(name); @@ -1369,6 +1398,8 @@ namespace spades { Player *player = world->GetLocalPlayer(); + def.blurVignette = .4f; + if(IsFollowing()){ int limit = 100; // if current following player has left, @@ -1541,6 +1572,15 @@ namespace spades { float per = aimDownState; per *= per * per; def.depthOfFieldNearRange = per * 13.f + .01f; + + def.blurVignette = .4f; + + float wTime = world->GetTime(); + if(wTime < lastHurtTime + .15f){ + float per = 1.f - (wTime - lastHurtTime) / .15f; + per *= .5f + player->GetHealth() / 100.f * .3f; + def.blurVignette += per * 5.f; + } } @@ -2905,6 +2945,44 @@ namespace spades { renderer->Flip(); } + void Client::DrawHurtSprites() { + float per = (world->GetTime() - lastHurtTime) / .6f; + if(per > 1.f) return; + IImage *img = renderer->RegisterImage("Gfx/HurtSprite.png"); + + Vector2 scrSize = {renderer->ScreenWidth(), renderer->ScreenHeight()}; + Vector2 scrCenter = scrSize * .5f; + float radius = scrSize.GetLength() * .5f; + + for(size_t i = 0 ; i < hurtSprites.size(); i++) { + HurtSprite& spr = hurtSprites[i]; + float alpha = spr.strength - per; + if(alpha < 0.f) continue; + if(alpha > 1.f) alpha = 1.f; + + Vector2 radDir = { + cosf(spr.angle), sinf(spr.angle) + }; + Vector2 angDir = { + -sinf(spr.angle), cosf(spr.angle) + }; + float siz = spr.scale * radius; + Vector2 base = radDir * radius + scrCenter; + Vector2 centVect = radDir * (-siz); + Vector2 sideVect1 = angDir * (siz * 4.f * (spr.horzShift)); + Vector2 sideVect2 = angDir * (siz * 4.f * (spr.horzShift - 1.f)); + + Vector2 v1 = base + centVect + sideVect1; + Vector2 v2 = base + centVect + sideVect2; + Vector2 v3 = base + sideVect1; + + renderer->SetColor(MakeVector4(0.f, 0.f, 0.f, alpha)); + renderer->DrawImage(img, + v1, v2, v3, + AABB2(0, 8.f, img->GetWidth(), img->GetHeight())); + } + } + void Client::Draw2D(){ SPADES_MARK_FUNCTION(); @@ -2925,8 +3003,14 @@ namespace spades { Player *p = GetWorld()->GetLocalPlayer(); if(p){ - if(wTime < lastHurtTime + .2f){ - float per = (wTime - lastHurtTime) / .2f; + DrawHurtSprites(); + + if(wTime < lastHurtTime + .35f){ + float per = (wTime - lastHurtTime) / .35f; + per = 1.f - per; + per *= .3f + p->GetHealth() / 100.f * .7f; + per = std::min(per, 0.9f); + per = 1.f - per; Vector3 color = {1.f, per, per}; renderer->MultiplyScreenColor(color); } diff --git a/Sources/Client/Client.h b/Sources/Client/Client.h index 3222ceb1..d19a2ad6 100644 --- a/Sources/Client/Client.h +++ b/Sources/Client/Client.h @@ -125,6 +125,13 @@ namespace spades { float lastAliveTime; int lastKills; float worldSetTime; + struct HurtSprite { + float angle; + float horzShift; + float scale; + float strength; + }; + std::vector hurtSprites; Player::ToolType selectedTool; float toolRaiseState; @@ -205,6 +212,7 @@ namespace spades { void DrawScene(); void Draw2D(); + void DrawHurtSprites(); std::string ScreenShotPath(); void TakeScreenShot(bool sceneOnly); diff --git a/Sources/Client/SceneDefinition.h b/Sources/Client/SceneDefinition.h index d2b32d0b..e10918e6 100644 --- a/Sources/Client/SceneDefinition.h +++ b/Sources/Client/SceneDefinition.h @@ -38,10 +38,13 @@ namespace spades { bool denyCameraBlur; + float blurVignette; + SceneDefinition() { depthOfFieldNearRange = 0.f; denyCameraBlur = true; time = 0; + blurVignette = 0.f; } }; } diff --git a/Sources/Draw/GLDepthOfFieldFilter.cpp b/Sources/Draw/GLDepthOfFieldFilter.cpp index afd17ed5..a06b96e0 100644 --- a/Sources/Draw/GLDepthOfFieldFilter.cpp +++ b/Sources/Draw/GLDepthOfFieldFilter.cpp @@ -89,7 +89,7 @@ namespace spades { return buf3; } - GLColorBuffer GLDepthOfFieldFilter::GenerateCoC(float blurDepthRange) { + GLColorBuffer GLDepthOfFieldFilter::GenerateCoC(float blurDepthRange, float vignetteBlur) { SPADES_MARK_FUNCTION(); IGLDevice *dev = renderer->GetGLDevice(); GLQuadRenderer qr(dev); @@ -138,7 +138,7 @@ namespace spades { vignetteScale.SetValue(2.f, 2.f * (float)h / (float)w); } - maxVignetteBlur.SetValue(sinf(std::max(def.fovX, def.fovY) * .5f) * .5f); + maxVignetteBlur.SetValue(sinf(std::max(def.fovX, def.fovY) * .5f) * vignetteBlur); qr.SetCoordAttributeIndex(positionAttribute()); dev->BindTexture(IGLDevice::Texture2D, renderer->GetFramebufferManager()->GetDepthTexture()); @@ -371,7 +371,7 @@ namespace spades { } - GLColorBuffer GLDepthOfFieldFilter::Filter(GLColorBuffer input, float blurDepthRange) { + GLColorBuffer GLDepthOfFieldFilter::Filter(GLColorBuffer input, float blurDepthRange, float vignetteBlur) { SPADES_MARK_FUNCTION(); IGLDevice *dev = renderer->GetGLDevice(); @@ -386,13 +386,15 @@ namespace spades { { GLProfiler p(dev, "CoC Computation"); - coc = GenerateCoC(blurDepthRange); + coc = GenerateCoC(blurDepthRange, vignetteBlur); } float maxCoc = (float)std::max(w, h) / 100.f; float cos60 = cosf(M_PI / 3.f); float sin60 = sinf(M_PI / 3.f); + maxCoc *= .7f + vignetteBlur * 0.5f; + // reduce resolution to make it faster int divide = 1; int siz = std::max(w, h); diff --git a/Sources/Draw/GLDepthOfFieldFilter.h b/Sources/Draw/GLDepthOfFieldFilter.h index b69d69bc..a21f4c59 100644 --- a/Sources/Draw/GLDepthOfFieldFilter.h +++ b/Sources/Draw/GLDepthOfFieldFilter.h @@ -37,7 +37,7 @@ namespace spades { GLProgram *blurProgram; // program to mix CoC radius GLProgram *finalMix; // program to mix CoC radius - GLColorBuffer GenerateCoC(float blurDepthRange); + GLColorBuffer GenerateCoC(float blurDepthRange, float vignetteBlur); GLColorBuffer BlurCoC(GLColorBuffer, float spread); GLColorBuffer Blur(GLColorBuffer, GLColorBuffer coc, @@ -51,7 +51,7 @@ namespace spades { GLColorBuffer UnderSample(GLColorBuffer); public: GLDepthOfFieldFilter(GLRenderer *); - GLColorBuffer Filter(GLColorBuffer, float blurDepthRange); + GLColorBuffer Filter(GLColorBuffer, float blurDepthRange, float vignetteBlur); }; } } diff --git a/Sources/Draw/GLRenderer.cpp b/Sources/Draw/GLRenderer.cpp index 84b7ff79..de8d735b 100644 --- a/Sources/Draw/GLRenderer.cpp +++ b/Sources/Draw/GLRenderer.cpp @@ -779,10 +779,13 @@ namespace spades { device->BlendFunc(IGLDevice::SrcAlpha, IGLDevice::OneMinusSrcAlpha); - if(r_depthOfField){ + if(r_depthOfField && + (sceneDef.depthOfFieldNearRange > 0.f || + sceneDef.blurVignette > 0.f)){ GLProfiler profiler(device, "Depth of Field"); handle = GLDepthOfFieldFilter(this).Filter(handle, - sceneDef.depthOfFieldNearRange); + sceneDef.depthOfFieldNearRange, + sceneDef.blurVignette); }