Skip to content

Commit

Permalink
small module for NPC interactions for use with dialogues / general use
Browse files Browse the repository at this point in the history
  • Loading branch information
ScuffedNewt committed Feb 9, 2024
1 parent cb7afdc commit 9db1460
Show file tree
Hide file tree
Showing 11 changed files with 332 additions and 1 deletion.
27 changes: 27 additions & 0 deletions app/Http/Controllers/Admin/Characters/CharacterController.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use App\Models\User\User;
use App\Models\User\UserItem;
use App\Services\CharacterManager;
use App\Services\NpcManager;
use App\Services\TradeManager;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
Expand Down Expand Up @@ -757,4 +758,30 @@ public function getMyoIndex() {
'slots' => Character::myo(1)->orderBy('id', 'DESC')->paginate(30),
]);
}

/**
* Updates a character's NPC status.
*
* @return \Illuminate\Contracts\Support\Renderable
*/
public function postEditNpcStatus(NpcManager $service, Request $request, $slug) {
$character = Character::where('slug', $slug)->first();
if (!$character) {
abort(404);
}

$data = $request->only([
'is_npc', 'biography_required_affection', 'biography', 'default_affection',
]);

if ($service->editCharacterNpcInformation($character, $data)) {
flash('Character NPC status updated successfully.')->success();
} else {
foreach ($service->errors()->getMessages()['error'] as $error) {
flash($error)->error();
}
}

return redirect()->back();
}
}
9 changes: 8 additions & 1 deletion app/Models/Character/Character.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class Character extends Model {
'is_sellable', 'is_tradeable', 'is_giftable',
'sale_value', 'transferrable_at', 'is_visible',
'is_gift_art_allowed', 'is_gift_writing_allowed', 'is_trading', 'sort',
'is_myo_slot', 'name', 'trade_id', 'owner_url',
'is_myo_slot', 'name', 'trade_id', 'owner_url', 'is_npc',
];

/**
Expand Down Expand Up @@ -191,6 +191,13 @@ public function items() {
return $this->belongsToMany(Item::class, 'character_items')->withPivot('count', 'data', 'updated_at', 'id')->whereNull('character_items.deleted_at');
}

/**
* Gets the characters NPC information.
*/
public function npcInformation() {
return $this->hasOne(CharacterNpcInformation::class, 'character_id');
}

/**********************************************************************************************
SCOPES
Expand Down
43 changes: 43 additions & 0 deletions app/Models/Character/CharacterNpcInformation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace App\Models\Character;

use App\Models\Model;

class CharacterNpcInformation extends Model {
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'character_id', 'biography', 'default_affection',
];

/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'character_npc_information';

/**
* The primary key of the model.
*
* @var string
*/
public $primaryKey = 'character_id';

/**********************************************************************************************
RELATIONS
**********************************************************************************************/

/**
* Get the character this profile belongs to.
*/
public function character() {
return $this->belongsTo(Character::class, 'character_id');
}
}
7 changes: 7 additions & 0 deletions app/Models/User/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,13 @@ public function commentLikes() {
return $this->hasMany(CommentLike::class);
}

/**
* Gets all of a user's NPC affection records.
*/
public function npcAffections() {
return $this->hasMany(UserNpcAffection::class);
}

/**********************************************************************************************
SCOPES
Expand Down
52 changes: 52 additions & 0 deletions app/Models/User/UserNpcAffection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

namespace App\Models\User;

use App\Models\Model;
use App\Models\Character\Character;

class UserNpcAffection extends Model {

/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'character_id', 'user_id', 'affection',
];

/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'user_npc_affection';

/**
* The primary key of the model.
*
* @var string
*/
public $primaryKey = 'user_id';

/**********************************************************************************************
RELATIONS
**********************************************************************************************/

/**
* Get the character this belongs to.
*/
public function character() {
return $this->belongsTo(Character::class);
}

/**
* Get the user this belongs to.
*/
public function user() {
return $this->belongsTo(User::class);
}
}
91 changes: 91 additions & 0 deletions app/Services/NpcManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php

namespace App\Services;

use App\Models\User\User;
use App\Models\User\UserNpcAffection;
use App\Models\Character\Character;
use Illuminate\Support\Facades\DB;

class NpcManager extends Service {

/**********************************************************************************************
*
* CHARACTER METHODS
*
**********************************************************************************************/

/**
* Updates a character's NPC status.
*
* @param Character $character
* @param array $data
*/
public function editCharacterNpcInformation(Character $character, array $data) {
DB::beginTransaction();

try {

if (!isset($data['is_npc'])) {
$character->npcInformation()->delete();
$character->is_npc = false;
$character->save();
} else {
$character->is_npc = true;
$character->save();

$npcInformation = $character->npcInformation;
if ($npcInformation) {
$npcInformation->update($data);
} else {
$npcInformation = $character->npcInformation()->create($data);
}
}

return $this->commitReturn(true);
} catch (\Exception $e) {
$this->setError('error', $e->getMessage());
}

return $this->rollbackReturn(false);
}

/**********************************************************************************************
*
* USER METHODS
*
**********************************************************************************************/

/**
* Updates a NPC's affection for a user.
*
* @param Character $character
* @param User $user
* @param int $quantity
*/
public function updateAffection(Character $character, User $user, int $quantity) {
DB::beginTransaction();

try {

$affection = $user->npcAffection()->where('character_id', $character->id)->first();

if ($affection) {
$affection->affection += $quantity;
$affection->save();
} else {
$user->npcAffection()->create([
'character_id' => $character->id,
'affection' => $quantity,
]);
}

return $this->commitReturn(true);
} catch (\Exception $e) {
$this->setError('error', $e->getMessage());
}

return $this->rollbackReturn(false);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateNpcCharacterTable extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('characters', function (Blueprint $table) {
$table->boolean('is_npc')->default(false);
});

Schema::create('character_npc_information', function (Blueprint $table) {
$table->id();
$table->integer('character_id')->unsigned();
$table->integer('default_affection')->unsigned()->default(0);
$table->text('biography')->nullable()->default(null);
$table->integer('biography_affection_requirement')->unsigned()->default(50);
});

Schema::create('user_npc_affection', function (Blueprint $table) {
$table->id();
$table->integer('character_id')->unsigned();
$table->integer('user_id')->unsigned();
$table->integer('affection')->unsigned()->default(0);
});
}

/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('characters', function (Blueprint $table) {
$table->dropColumn('is_npc');
});
Schema::dropIfExists('character_npc_information');
Schema::dropIfExists('user_npc_affection');
}
};
3 changes: 3 additions & 0 deletions resources/views/browse/_masterlist_content.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@
</div>
<div class="mt-1">
<a href="{{ $character->url }}" class="h5 mb-0">
@if ($character->is_npc)
<i class="fas fa-user-ninja"></i>
@endif
@if (!$character->is_visible)
<i class="fas fa-eye-slash"></i>
@endif {{ Illuminate\Support\Str::limit($character->fullName, 20, $end = '...') }}
Expand Down
16 changes: 16 additions & 0 deletions resources/views/character/_affection.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
@php
$affection = $user->npcAffections->where('npc_id', $character->id)->first();
if (!$affection) {
$affection = $user->npcAffections()->create([
'character_id' => $character->id,
'affection' => $character->npcInformation->default_affection ?? 0,
]);
}
@endphp

{{-- progress bar --}}
<div class="progress mb-3">
<div class="progress-bar bg-success progress-bar-striped progress-bar-animated" role="progressbar" style="width: {{ $affection->affection }}%" aria-valuenow="{{ $affection->affection }}" aria-valuemin="0" aria-valuemax="100">
{{ $affection->affection }}% Affection
</div>
</div>
38 changes: 38 additions & 0 deletions resources/views/character/character.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@

@include('character._header', ['character' => $character])

@if (Auth::check())
@include('character._affection', ['character' => $character, 'user' => Auth::user()])
@endif

{{-- Main Image --}}
<div class="row mb-3">
<div class="col-md-7">
Expand Down Expand Up @@ -73,6 +77,40 @@ class="image" alt="{{ $character->fullName }}" />
</div>
{!! Form::close() !!}
<hr />
@if (!$character->is_myo_slot)
{!! Form::open(['url' => 'admin/character/' . $character->slug . '/npc']) !!}

<div class="form-group">
{!! Form::checkbox('is_npc', 1, $character->is_npc, ['class' => 'form-check-input', 'data-toggle' => 'toggle', 'id' => 'npc']) !!}
{!! Form::label('is_npc', 'Is NPC', ['class' => 'form-check-label ml-3']) !!} {!! add_help('Turn this on to mark the character as an NPC. This will modify the character\'s page to present as an NPC.') !!}
</div>

@if ($character->is_npc)
<div class="form-group">
<div class="row">
<div class="col-md-6">
{!! Form::label('default_affection', 'Default Affection') !!} {!! add_help('The default affection level for this NPC, on a scale of 0-100.') !!}
{!! Form::number('default_affection', $character->npcInformation?->default_affection ?? 0, ['class' => 'form-control', 'min' => 0, 'max' => 100]) !!}
</div>
<div class="col-md-6">
{!! Form::label('biography_affection_requirement', 'Biography Affection Requirement') !!} {!! add_help('The affection level required to view the biography of this NPC.') !!}
{!! Form::number('biography_affection_requirement', $character->npcInformation?->biography_affection_requirement ?? 50, ['class' => 'form-control', 'min' => 0, 'max' => 100]) !!}
</div>
</div>
</div>

{{-- biography, wisywg editor --}}
<div class="form-group">
{!! Form::label('biography', 'Biography') !!} {!! add_help('The biography of the NPC. Biographys become available when affection is above 50.') !!}
{!! Form::textarea('biography', $character->npcInformation?->biography, ['class' => 'form-control wysiwyg', 'rows' => 5]) !!}
</div>
@endif
<div class="text-right">
{!! Form::submit('Edit', ['class' => 'btn btn-primary']) !!}
</div>
{!! Form::close() !!}
<hr />
@endif
<div class="text-right">
<a href="#" class="btn btn-outline-danger btn-sm delete-character" data-slug="{{ $character->slug }}">Delete</a>
</div>
Expand Down
2 changes: 2 additions & 0 deletions routes/lorekeeper/admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,8 @@
Route::post('{slug}/settings', 'CharacterController@postCharacterSettings');

Route::post('{slug}/transfer', 'CharacterController@postTransfer');

Route::post('{slug}/npc', 'CharacterController@postEditNpcStatus');
});
// Might rewrite these parts eventually so there's less code duplication...
Route::group(['prefix' => 'myo', 'namespace' => 'Characters', 'middleware' => 'power:manage_characters'], function () {
Expand Down

0 comments on commit 9db1460

Please sign in to comment.