Compare commits

...

1 Commits

Author SHA1 Message Date
Flatlogic Bot
ef44030a6c Autosave: 20260305-110247 2026-03-05 11:02:47 +00:00
22 changed files with 264 additions and 43 deletions

View File

@ -20,7 +20,8 @@ from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path("admin/", admin.site.urls),
path('admin/', admin.site.urls),
path('accounts/', include('django.contrib.auth.urls')),
path("", include("core.urls")),
]

View File

@ -0,0 +1,63 @@
# Generated by Django 5.2.7 on 2026-03-05 10:42
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Item',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
('description', models.TextField()),
],
),
migrations.CreateModel(
name='Quest',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=100)),
('description', models.TextField()),
('is_active', models.BooleanField(default=False)),
('is_completed', models.BooleanField(default=False)),
],
),
migrations.CreateModel(
name='Scene',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=200)),
('content', models.TextField()),
],
),
migrations.CreateModel(
name='PlayerProfile',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('level', models.IntegerField(default=1)),
('inventory', models.ManyToManyField(blank=True, to='core.item')),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
('quests', models.ManyToManyField(blank=True, to='core.quest')),
('current_scene', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='core.scene')),
],
),
migrations.CreateModel(
name='Choice',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('text', models.CharField(max_length=200)),
('next_scene', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='incoming_choices', to='core.scene')),
('scene', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='choices', to='core.scene')),
],
),
]

View File

@ -1,3 +1,43 @@
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Item(models.Model):
name = models.CharField(max_length=100)
description = models.TextField()
def __str__(self):
return self.name
class Quest(models.Model):
title = models.CharField(max_length=100)
description = models.TextField()
is_active = models.BooleanField(default=False)
is_completed = models.BooleanField(default=False)
def __str__(self):
return self.title
class Scene(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
def __str__(self):
return self.title
class Choice(models.Model):
scene = models.ForeignKey(Scene, related_name='choices', on_delete=models.CASCADE)
text = models.CharField(max_length=200)
next_scene = models.ForeignKey(Scene, related_name='incoming_choices', on_delete=models.SET_NULL, null=True, blank=True)
def __str__(self):
return self.text
class PlayerProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
current_scene = models.ForeignKey(Scene, on_delete=models.SET_NULL, null=True, blank=True)
inventory = models.ManyToManyField(Item, blank=True)
quests = models.ManyToManyField(Quest, blank=True)
level = models.IntegerField(default=1)
def __str__(self):
return self.user.username

View File

@ -3,23 +3,33 @@
<head>
<meta charset="UTF-8">
<title>{% block title %}Knowledge Base{% endblock %}</title>
{% if project_description %}
<meta name="description" content="{{ project_description }}">
<meta property="og:description" content="{{ project_description }}">
<meta property="twitter:description" content="{{ project_description }}">
{% endif %}
{% if project_image_url %}
<meta property="og:image" content="{{ project_image_url }}">
<meta property="twitter:image" content="{{ project_image_url }}">
{% endif %}
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}Witcher RPG{% endblock %}</title>
{% load static %}
<link rel="stylesheet" href="{% static 'css/custom.css' %}?v={{ deployment_timestamp }}">
<!-- Google Fonts for Cinzel and Inter -->
<link href="https://fonts.googleapis.com/css2?family=Cinzel:wght@400;700&family=Inter:wght@400;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="{% static 'css/custom.css' %}?v=1.0">
{% block head %}{% endblock %}
</head>
<body>
{% block content %}{% endblock %}
<body style="background-color: #0F1310; color: #E0E0E0; font-family: 'Inter', sans-serif; margin: 0; padding: 0;">
<header style="padding: 20px; border-bottom: 2px solid #333;">
<h1 style="font-family: 'Cinzel', serif; color: #B68D4C; margin: 0;">Witcher RPG</h1>
<nav>
<a href="{% url 'core:home' %}" style="color: #D4B26A; margin-right: 15px;">Home</a>
<a href="{% url 'core:current_scene' %}" style="color: #D4B26A; margin-right: 15px;">Play</a>
</nav>
</header>
<main style="padding: 20px;">
{% block content %}{% endblock %}
</main>
<footer style="padding: 20px; text-align: center; color: #88938C; font-size: 0.8em; margin-top: 50px;">
&copy; 2026 Dark Fantasy RPG Engine
</footer>
</body>
</html>
</html>

View File

@ -0,0 +1,36 @@
{% extends "base.html" %}
{% load static %}
{% block content %}
<div class="row">
<div class="col-md-8">
<div class="card">
<h1>{{ scene.title }}</h1>
<p>{{ scene.content }}</p>
</div>
<div class="actions">
{% for choice in scene.choices.all %}
<a href="{% url 'core:choose_action' choice.id %}" class="btn btn-accent" style="display: block; margin-bottom: 10px;">{{ choice.text }}</a>
{% endfor %}
</div>
</div>
<div class="col-md-4">
<div class="card" style="background-color: #1C2320; border: 1px solid #333; padding: 15px;">
<h2 style="color: #B68D4C; font-size: 1.2em;">Character Status</h2>
<p>Level: {{ player.level }}</p>
<h3 style="color: #B68D4C; font-size: 1.1em;">Quests</h3>
<ul>
{% for quest in player.quests.all %}
<li>{{ quest.title }} - {{ quest.is_completed|yesno:"Completed,Active" }}</li>
{% endfor %}
</ul>
<h3 style="color: #B68D4C; font-size: 1.1em;">Inventory</h3>
<ul>
{% for item in player.inventory.all %}
<li>{{ item.name }}</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,34 @@
{% extends "base.html" %}
{% block title %}Sign In | Witcher RPG{% endblock %}
{% block content %}
<section style="max-width: 480px; margin: 40px auto; background: #1C2320; border: 1px solid #2F3A34; border-radius: 12px; padding: 28px; box-shadow: 0 12px 30px rgba(0,0,0,0.35);">
<h2 style="font-family: 'Cinzel', serif; color: #D4B26A; margin-top: 0;">Sign in to continue</h2>
<p style="color: #A8B1AA; margin-bottom: 24px;">Enter your credentials to resume your journey.</p>
{% if form.non_field_errors %}
<div style="background: rgba(190, 64, 64, 0.15); border: 1px solid #8C3B3B; color: #F2B8B5; padding: 12px; border-radius: 8px; margin-bottom: 16px;">
{{ form.non_field_errors }}
</div>
{% endif %}
<form method="post" style="display: grid; gap: 16px;">
{% csrf_token %}
<label style="display: grid; gap: 6px; color: #D4B26A;">
<span>Username</span>
{{ form.username }}
</label>
<label style="display: grid; gap: 6px; color: #D4B26A;">
<span>Password</span>
{{ form.password }}
</label>
<button type="submit" style="background: linear-gradient(135deg, #B68D4C, #D4B26A); color: #0F1310; border: none; padding: 12px 18px; border-radius: 10px; font-weight: 700; cursor: pointer;">
Sign In
</button>
</form>
</section>
{% endblock %}

View File

@ -1,7 +1,11 @@
from django.urls import path
from . import views
from .views import home
app_name = 'core'
urlpatterns = [
path("", home, name="home"),
]
path('', views.home, name='home'),
path('scene/<int:scene_id>/', views.scene_view, name='scene_detail'),
path('scene/', views.scene_view, name='current_scene'),
path('choose/<int:choice_id>/', views.choose_action, name='choose_action'),
]

View File

@ -1,25 +1,36 @@
import os
import platform
from django import get_version as django_version
from django.shortcuts import render
from django.utils import timezone
from django.shortcuts import render, get_object_or_404, redirect
from .models import Scene, Choice, PlayerProfile
from django.contrib.auth.decorators import login_required
def home(request):
"""Render the landing screen with loader and environment details."""
host_name = request.get_host().lower()
agent_brand = "AppWizzy" if host_name == "appwizzy.com" else "Flatlogic"
now = timezone.now()
return render(request, "core/index.html")
context = {
"project_name": "New Style",
"agent_brand": agent_brand,
"django_version": django_version(),
"python_version": platform.python_version(),
"current_time": now,
"host_name": host_name,
"project_description": os.getenv("PROJECT_DESCRIPTION", ""),
"project_image_url": os.getenv("PROJECT_IMAGE_URL", ""),
}
return render(request, "core/index.html", context)
@login_required
def scene_view(request, scene_id=None):
player = request.user.playerprofile
if scene_id:
scene = get_object_or_404(Scene, id=scene_id)
player.current_scene = scene
player.save()
else:
scene = player.current_scene
if not scene:
first_scene = Scene.objects.first()
if first_scene:
player.current_scene = first_scene
player.save()
scene = first_scene
else:
return render(request, "core/empty.html")
return render(request, "core/scene_detail.html", {"scene": scene, "player": player})
@login_required
def choose_action(request, choice_id):
choice = get_object_or_404(Choice, id=choice_id)
player = request.user.playerprofile
if choice.next_scene:
player.current_scene = choice.next_scene
player.save()
return redirect('core:scene_detail', scene_id=choice.next_scene.id)
return redirect('core:current_scene')

View File

@ -1,4 +1,26 @@
/* Custom styles for the application */
body {
font-family: system-ui, -apple-system, sans-serif;
background-color: #0F1310;
color: #E0E0E0;
font-family: 'Inter', sans-serif;
}
h1, h2, h3 {
font-family: 'Cinzel', serif;
color: #B68D4C;
}
.btn-accent {
background-color: #B68D4C;
color: #0F1310;
border: none;
padding: 10px 20px;
text-transform: uppercase;
font-weight: bold;
}
.card {
background-color: #1C2320;
border: 1px solid #333;
padding: 20px;
margin-bottom: 20px;
}